@polka-codes/cli 0.4.10 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +532 -407
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10053,15 +10053,15 @@ var require_route = __commonJS((exports, module) => {
|
|
|
10053
10053
|
};
|
|
10054
10054
|
}
|
|
10055
10055
|
function wrapConversion(toModel, graph) {
|
|
10056
|
-
const
|
|
10056
|
+
const path = [graph[toModel].parent, toModel];
|
|
10057
10057
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
10058
10058
|
let cur = graph[toModel].parent;
|
|
10059
10059
|
while (graph[cur].parent) {
|
|
10060
|
-
|
|
10060
|
+
path.unshift(graph[cur].parent);
|
|
10061
10061
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
10062
10062
|
cur = graph[cur].parent;
|
|
10063
10063
|
}
|
|
10064
|
-
fn.conversion =
|
|
10064
|
+
fn.conversion = path;
|
|
10065
10065
|
return fn;
|
|
10066
10066
|
}
|
|
10067
10067
|
module.exports = function(fromModel) {
|
|
@@ -24629,7 +24629,7 @@ var {
|
|
|
24629
24629
|
Help
|
|
24630
24630
|
} = import__.default;
|
|
24631
24631
|
// package.json
|
|
24632
|
-
var version = "0.
|
|
24632
|
+
var version = "0.5.1";
|
|
24633
24633
|
|
|
24634
24634
|
// ../../node_modules/@anthropic-ai/sdk/version.mjs
|
|
24635
24635
|
var VERSION = "0.36.2";
|
|
@@ -33262,7 +33262,7 @@ var toolInfo = {
|
|
|
33262
33262
|
},
|
|
33263
33263
|
{
|
|
33264
33264
|
name: "options",
|
|
33265
|
-
description: "A comma separated list of possible answers to the question. If not provided, the user will be prompted to provide an answer.",
|
|
33265
|
+
description: "A comma separated list of possible answers to the question. Ordered by preference. If not provided, the user will be prompted to provide an answer.",
|
|
33266
33266
|
required: false,
|
|
33267
33267
|
usageValue: "A comma separated list of possible answers (optional)"
|
|
33268
33268
|
}
|
|
@@ -34874,8 +34874,80 @@ class MultiAgent {
|
|
|
34874
34874
|
|
|
34875
34875
|
// ../core/src/Agent/index.ts
|
|
34876
34876
|
var allAgents = [architectAgentInfo, coderAgentInfo, analyzerAgentInfo];
|
|
34877
|
+
// ../core/src/AiTool/createNewProject.ts
|
|
34878
|
+
var prompt = `You are an AiTool designed to assist users in creating new projects. Follow these guidelines:
|
|
34879
|
+
|
|
34880
|
+
1. **Gather Information:**
|
|
34881
|
+
- Begin by asking the user for essential project details, including:
|
|
34882
|
+
- Project type (e.g., web, mobile, desktop, etc.)
|
|
34883
|
+
- Desired programming languages
|
|
34884
|
+
- Preferred frameworks or libraries
|
|
34885
|
+
- Build tools and package manager preferences
|
|
34886
|
+
- Testing frameworks and patterns
|
|
34887
|
+
- Code style and linting preferences
|
|
34888
|
+
- Any additional specifications or requirements
|
|
34889
|
+
|
|
34890
|
+
2. **Clarification & Confirmation:**
|
|
34891
|
+
- Do not make any decisions or assumptions on behalf of the user.
|
|
34892
|
+
- Ask clarifying questions if any detail is ambiguous.
|
|
34893
|
+
- Confirm each piece of information with the user before proceeding to the next step.
|
|
34894
|
+
|
|
34895
|
+
3. **Avoid Redundancy:**
|
|
34896
|
+
- Do not repeat questions or details that have already been confirmed.
|
|
34897
|
+
- Keep interactions concise and focused on gathering complete and accurate details.
|
|
34898
|
+
|
|
34899
|
+
4. **Generate Configuration:**
|
|
34900
|
+
- Based on the collected information, generate a .polkacodes.yml configuration file that includes:
|
|
34901
|
+
- scripts section with common development commands (test, format, check, etc.)
|
|
34902
|
+
- rules section reflecting project conventions and tools
|
|
34903
|
+
- excludeFiles section for sensitive and generated files
|
|
34904
|
+
- Example structure:
|
|
34905
|
+
\`\`\`yaml
|
|
34906
|
+
scripts:
|
|
34907
|
+
test:
|
|
34908
|
+
command: "[test-command]"
|
|
34909
|
+
description: "Run tests"
|
|
34910
|
+
format:
|
|
34911
|
+
command: "[format-command]"
|
|
34912
|
+
description: "Format code"
|
|
34913
|
+
check:
|
|
34914
|
+
command: "[check-command]"
|
|
34915
|
+
description: "Check code"
|
|
34916
|
+
|
|
34917
|
+
rules:
|
|
34918
|
+
- "[package-manager-rule]"
|
|
34919
|
+
- "[testing-framework-rule]"
|
|
34920
|
+
- "[code-style-rule]"
|
|
34921
|
+
- "[other-rule]"
|
|
34922
|
+
|
|
34923
|
+
excludeFiles:
|
|
34924
|
+
- ".env"
|
|
34925
|
+
- ".env.*"
|
|
34926
|
+
\`\`\`
|
|
34927
|
+
|
|
34928
|
+
5. **Handover to Coder Agent:**
|
|
34929
|
+
- Once all required information is collected and validated by the user, compile:
|
|
34930
|
+
1. The final project specifications
|
|
34931
|
+
2. The .polkacodes.yml configuration content
|
|
34932
|
+
- Clearly hand over these details to the coder agent, instructing them to:
|
|
34933
|
+
1. Create the new project based on the confirmed specifications
|
|
34934
|
+
2. Include the .polkacodes.yml file in the project root
|
|
34935
|
+
3. Ensure all specified tools and configurations are properly set up`;
|
|
34936
|
+
var createNewProject_default = {
|
|
34937
|
+
name: "createNewProject",
|
|
34938
|
+
description: "Creates a new project",
|
|
34939
|
+
prompt,
|
|
34940
|
+
formatInput: (params) => {
|
|
34941
|
+
return `<project_name>${params}</project_name>`;
|
|
34942
|
+
},
|
|
34943
|
+
parseOutput: (output) => {
|
|
34944
|
+
return output.trim();
|
|
34945
|
+
},
|
|
34946
|
+
agent: "architect"
|
|
34947
|
+
};
|
|
34948
|
+
|
|
34877
34949
|
// ../core/src/AiTool/generateGitCommitMessage.ts
|
|
34878
|
-
var
|
|
34950
|
+
var prompt2 = `
|
|
34879
34951
|
You are an advanced assistant specialized in creating concise and accurate Git commit messages. When you receive:
|
|
34880
34952
|
- A Git diff inside the <tool_input> tag.
|
|
34881
34953
|
- Additional user-supplied context inside the <tool_input_context> tag (if any).
|
|
@@ -34910,7 +34982,7 @@ Follow the same structure for any new input. Never repeat questions; focus on ge
|
|
|
34910
34982
|
var generateGitCommitMessage_default = {
|
|
34911
34983
|
name: "generateGitCommitMessage",
|
|
34912
34984
|
description: "Generates git commit messages from git diff output",
|
|
34913
|
-
prompt,
|
|
34985
|
+
prompt: prompt2,
|
|
34914
34986
|
formatInput: (params) => {
|
|
34915
34987
|
let ret = `<tool_input>
|
|
34916
34988
|
${params.diff}
|
|
@@ -34935,7 +35007,7 @@ ${output}`);
|
|
|
34935
35007
|
};
|
|
34936
35008
|
|
|
34937
35009
|
// ../core/src/AiTool/generateGithubPullRequestDetails.ts
|
|
34938
|
-
var
|
|
35010
|
+
var prompt3 = `
|
|
34939
35011
|
# Generate Github Pull Request Details
|
|
34940
35012
|
|
|
34941
35013
|
You are given:
|
|
@@ -35019,7 +35091,7 @@ Use the above format whenever you receive <tool_input> that may include a branch
|
|
|
35019
35091
|
var generateGithubPullRequestDetails_default = {
|
|
35020
35092
|
name: "generateGithubPullRequestDetails",
|
|
35021
35093
|
description: "Generates a GitHub pull request title and description from git commits",
|
|
35022
|
-
prompt:
|
|
35094
|
+
prompt: prompt3,
|
|
35023
35095
|
formatInput: (params) => {
|
|
35024
35096
|
return `<tool_input>
|
|
35025
35097
|
<tool_input_branch_name>${params.branchName}</tool_input_branch_name>${params.context ? `
|
|
@@ -35052,7 +35124,7 @@ ${output}`);
|
|
|
35052
35124
|
};
|
|
35053
35125
|
|
|
35054
35126
|
// ../core/src/AiTool/generateProjectConfig.ts
|
|
35055
|
-
var
|
|
35127
|
+
var prompt4 = `You are an analyzer agent responsible for examining project files and generating appropriate polkacodes configuration. Your task is to:
|
|
35056
35128
|
|
|
35057
35129
|
1. Read and analyze the provided files using tool_read_file to understand:
|
|
35058
35130
|
- Build tools and package manager (e.g., bun, npm)
|
|
@@ -35119,7 +35191,7 @@ The configuration should accurately reflect the project's structure, tools, and
|
|
|
35119
35191
|
var generateProjectConfig_default = {
|
|
35120
35192
|
name: "generateProjectConfig",
|
|
35121
35193
|
description: "Analyzes project files to generate polkacodes config sections",
|
|
35122
|
-
prompt:
|
|
35194
|
+
prompt: prompt4,
|
|
35123
35195
|
formatInput: (params) => {
|
|
35124
35196
|
return `<tool_input>
|
|
35125
35197
|
${params.join(`
|
|
@@ -35170,6 +35242,7 @@ var makeAgentTool = (definition) => {
|
|
|
35170
35242
|
var generateGitCommitMessage = makeTool(generateGitCommitMessage_default);
|
|
35171
35243
|
var generateGithubPullRequestDetails = makeTool(generateGithubPullRequestDetails_default);
|
|
35172
35244
|
var generateProjectConfig = makeAgentTool(generateProjectConfig_default);
|
|
35245
|
+
var createNewProject = makeAgentTool(createNewProject_default);
|
|
35173
35246
|
// src/Chat.ts
|
|
35174
35247
|
import readline from "node:readline";
|
|
35175
35248
|
|
|
@@ -35309,357 +35382,6 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
35309
35382
|
import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
35310
35383
|
import { dirname } from "node:path";
|
|
35311
35384
|
|
|
35312
|
-
// src/utils/listFiles.ts
|
|
35313
|
-
var import_ignore = __toESM(require_ignore(), 1);
|
|
35314
|
-
import { promises as fs2 } from "node:fs";
|
|
35315
|
-
import { join, relative, resolve } from "node:path";
|
|
35316
|
-
var DEFAULT_IGNORES = [
|
|
35317
|
-
"__pycache__",
|
|
35318
|
-
".DS_Store",
|
|
35319
|
-
".env",
|
|
35320
|
-
".git",
|
|
35321
|
-
".idea",
|
|
35322
|
-
".svn",
|
|
35323
|
-
".temp",
|
|
35324
|
-
".vscode",
|
|
35325
|
-
"coverage",
|
|
35326
|
-
"dist",
|
|
35327
|
-
"node_modules",
|
|
35328
|
-
"out",
|
|
35329
|
-
"Thumbs.db"
|
|
35330
|
-
];
|
|
35331
|
-
async function extendPatterns(basePatterns, dirPath) {
|
|
35332
|
-
try {
|
|
35333
|
-
const gitignorePath = join(dirPath, ".gitignore");
|
|
35334
|
-
const content = await fs2.readFile(gitignorePath, "utf8");
|
|
35335
|
-
const lines = content.split(/\r?\n/).filter(Boolean);
|
|
35336
|
-
return [...basePatterns, ...lines];
|
|
35337
|
-
} catch {
|
|
35338
|
-
return basePatterns;
|
|
35339
|
-
}
|
|
35340
|
-
}
|
|
35341
|
-
function createIgnore(patterns) {
|
|
35342
|
-
return import_ignore.default().add(patterns);
|
|
35343
|
-
}
|
|
35344
|
-
async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles) {
|
|
35345
|
-
let rootPatterns = [...DEFAULT_IGNORES, ...excludeFiles || []];
|
|
35346
|
-
try {
|
|
35347
|
-
const rootGitignore = await fs2.readFile(join(cwd, ".gitignore"), "utf8");
|
|
35348
|
-
const lines = rootGitignore.split(/\r?\n/).filter(Boolean);
|
|
35349
|
-
rootPatterns = [...rootPatterns, ...lines];
|
|
35350
|
-
} catch {
|
|
35351
|
-
}
|
|
35352
|
-
const results = [];
|
|
35353
|
-
const queue = [{ path: resolve(dirPath), patterns: rootPatterns }];
|
|
35354
|
-
while (queue.length > 0) {
|
|
35355
|
-
const { path: currentPath, patterns: parentPatterns } = queue.shift();
|
|
35356
|
-
const mergedPatterns = await extendPatterns(parentPatterns, currentPath);
|
|
35357
|
-
const folderIg = createIgnore(mergedPatterns);
|
|
35358
|
-
const entries = await fs2.readdir(currentPath, { withFileTypes: true });
|
|
35359
|
-
for (const entry of entries) {
|
|
35360
|
-
const fullPath = join(currentPath, entry.name);
|
|
35361
|
-
const relPath = relative(cwd, fullPath).replace(/\\/g, "/");
|
|
35362
|
-
if (folderIg.ignores(relPath)) {
|
|
35363
|
-
continue;
|
|
35364
|
-
}
|
|
35365
|
-
if (entry.isDirectory()) {
|
|
35366
|
-
if (recursive) {
|
|
35367
|
-
queue.push({ path: fullPath, patterns: mergedPatterns });
|
|
35368
|
-
}
|
|
35369
|
-
} else {
|
|
35370
|
-
results.push(relPath);
|
|
35371
|
-
if (results.length >= maxCount) {
|
|
35372
|
-
results.sort();
|
|
35373
|
-
return [results, true];
|
|
35374
|
-
}
|
|
35375
|
-
}
|
|
35376
|
-
}
|
|
35377
|
-
}
|
|
35378
|
-
results.sort();
|
|
35379
|
-
return [results, false];
|
|
35380
|
-
}
|
|
35381
|
-
|
|
35382
|
-
// src/utils/searchFiles.ts
|
|
35383
|
-
import { spawn } from "node:child_process";
|
|
35384
|
-
|
|
35385
|
-
// ../../node_modules/@vscode/ripgrep/lib/index.js
|
|
35386
|
-
var __dirname = "/Users/xiliangchen/projects/polka-codes/node_modules/@vscode/ripgrep/lib";
|
|
35387
|
-
var path = __require("path");
|
|
35388
|
-
var $rgPath = path.join(__dirname, `../bin/rg${process.platform === "win32" ? ".exe" : ""}`);
|
|
35389
|
-
|
|
35390
|
-
// src/utils/searchFiles.ts
|
|
35391
|
-
async function searchFiles(path2, regex, filePattern, cwd, excludeFiles) {
|
|
35392
|
-
const args = [
|
|
35393
|
-
"--line-number",
|
|
35394
|
-
"--context=5",
|
|
35395
|
-
"--color=never",
|
|
35396
|
-
"--with-filename",
|
|
35397
|
-
"--smart-case"
|
|
35398
|
-
];
|
|
35399
|
-
if (filePattern && filePattern !== "*") {
|
|
35400
|
-
args.push("--glob", filePattern);
|
|
35401
|
-
}
|
|
35402
|
-
if (excludeFiles) {
|
|
35403
|
-
for (const pattern of excludeFiles) {
|
|
35404
|
-
args.push("--ignore-file", pattern);
|
|
35405
|
-
}
|
|
35406
|
-
}
|
|
35407
|
-
args.push(regex, path2);
|
|
35408
|
-
return new Promise((resolve2, reject) => {
|
|
35409
|
-
const results = [];
|
|
35410
|
-
const rg = spawn($rgPath, args, {
|
|
35411
|
-
cwd,
|
|
35412
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
35413
|
-
});
|
|
35414
|
-
rg.stdout.on("data", (data) => {
|
|
35415
|
-
const lines = data.toString().split(`
|
|
35416
|
-
`).filter(Boolean);
|
|
35417
|
-
results.push(...lines);
|
|
35418
|
-
});
|
|
35419
|
-
rg.stderr.on("data", (data) => {
|
|
35420
|
-
const err = data.toString();
|
|
35421
|
-
if (!err.startsWith("WARNING:")) {
|
|
35422
|
-
console.warn(err);
|
|
35423
|
-
}
|
|
35424
|
-
});
|
|
35425
|
-
rg.on("error", (error) => {
|
|
35426
|
-
reject(new Error(`Failed to execute ripgrep: ${error.message}`));
|
|
35427
|
-
});
|
|
35428
|
-
rg.on("close", (code) => {
|
|
35429
|
-
if (code !== 0 && code !== 1) {
|
|
35430
|
-
reject(new Error(`Ripgrep process exited with code ${code}`));
|
|
35431
|
-
return;
|
|
35432
|
-
}
|
|
35433
|
-
resolve2(results);
|
|
35434
|
-
});
|
|
35435
|
-
});
|
|
35436
|
-
}
|
|
35437
|
-
|
|
35438
|
-
// src/provider.ts
|
|
35439
|
-
var getProvider = (agentName, config, options = {}) => {
|
|
35440
|
-
const ig = import_ignore2.default().add(options.excludeFiles ?? []);
|
|
35441
|
-
const provider2 = {
|
|
35442
|
-
readFile: async (path2) => {
|
|
35443
|
-
if (ig.ignores(path2)) {
|
|
35444
|
-
throw new Error(`Not allow to access file ${path2}`);
|
|
35445
|
-
}
|
|
35446
|
-
return await readFile(path2, "utf8");
|
|
35447
|
-
},
|
|
35448
|
-
writeFile: async (path2, content) => {
|
|
35449
|
-
if (ig.ignores(path2)) {
|
|
35450
|
-
throw new Error(`Not allow to access file ${path2}`);
|
|
35451
|
-
}
|
|
35452
|
-
await mkdir(dirname(path2), { recursive: true });
|
|
35453
|
-
return await writeFile(path2, content, "utf8");
|
|
35454
|
-
},
|
|
35455
|
-
removeFile: async (path2) => {
|
|
35456
|
-
if (ig.ignores(path2)) {
|
|
35457
|
-
throw new Error(`Not allow to access file ${path2}`);
|
|
35458
|
-
}
|
|
35459
|
-
return await unlink(path2);
|
|
35460
|
-
},
|
|
35461
|
-
renameFile: async (sourcePath, targetPath) => {
|
|
35462
|
-
if (ig.ignores(sourcePath) || ig.ignores(targetPath)) {
|
|
35463
|
-
throw new Error(`Not allow to access file ${sourcePath} or ${targetPath}`);
|
|
35464
|
-
}
|
|
35465
|
-
return await rename(sourcePath, targetPath);
|
|
35466
|
-
},
|
|
35467
|
-
listFiles: async (path2, recursive, maxCount) => {
|
|
35468
|
-
return await listFiles(path2, recursive, maxCount, dirname(path2), options.excludeFiles);
|
|
35469
|
-
},
|
|
35470
|
-
searchFiles: async (path2, regex, filePattern) => {
|
|
35471
|
-
return await searchFiles(path2, regex, filePattern, dirname(path2), options.excludeFiles);
|
|
35472
|
-
},
|
|
35473
|
-
executeCommand: (command, needApprove) => {
|
|
35474
|
-
return new Promise((resolve2, reject) => {
|
|
35475
|
-
options.command?.onStarted(command);
|
|
35476
|
-
const child = spawn2(command, [], {
|
|
35477
|
-
shell: true,
|
|
35478
|
-
stdio: "pipe"
|
|
35479
|
-
});
|
|
35480
|
-
let stdoutText = "";
|
|
35481
|
-
let stderrText = "";
|
|
35482
|
-
child.stdout.on("data", (data) => {
|
|
35483
|
-
const dataStr = data.toString();
|
|
35484
|
-
options.command?.onStdout(dataStr);
|
|
35485
|
-
stdoutText += dataStr;
|
|
35486
|
-
});
|
|
35487
|
-
child.stderr.on("data", (data) => {
|
|
35488
|
-
const dataStr = data.toString();
|
|
35489
|
-
options.command?.onStderr(dataStr);
|
|
35490
|
-
stderrText += dataStr;
|
|
35491
|
-
});
|
|
35492
|
-
child.on("close", (code) => {
|
|
35493
|
-
options.command?.onExit(code ?? 0);
|
|
35494
|
-
resolve2({
|
|
35495
|
-
stdout: stdoutText,
|
|
35496
|
-
stderr: stderrText,
|
|
35497
|
-
exitCode: code ?? 0
|
|
35498
|
-
});
|
|
35499
|
-
});
|
|
35500
|
-
child.on("error", (err) => {
|
|
35501
|
-
options.command?.onError(err);
|
|
35502
|
-
reject(err);
|
|
35503
|
-
});
|
|
35504
|
-
});
|
|
35505
|
-
},
|
|
35506
|
-
attemptCompletion: async (result) => {
|
|
35507
|
-
return;
|
|
35508
|
-
}
|
|
35509
|
-
};
|
|
35510
|
-
return provider2;
|
|
35511
|
-
};
|
|
35512
|
-
|
|
35513
|
-
// src/Runner.ts
|
|
35514
|
-
class Runner {
|
|
35515
|
-
#options;
|
|
35516
|
-
#multiAgent;
|
|
35517
|
-
#usageMeter;
|
|
35518
|
-
constructor(options) {
|
|
35519
|
-
this.#options = options;
|
|
35520
|
-
this.#usageMeter = new UsageMeter({
|
|
35521
|
-
maxCost: options.budget,
|
|
35522
|
-
maxMessageCount: options.maxMessageCount
|
|
35523
|
-
});
|
|
35524
|
-
const service = createService(options.provider, {
|
|
35525
|
-
apiKey: options.apiKey,
|
|
35526
|
-
model: options.model,
|
|
35527
|
-
usageMeter: this.#usageMeter,
|
|
35528
|
-
enableCache: options.enableCache
|
|
35529
|
-
});
|
|
35530
|
-
let rules2 = options.config.rules;
|
|
35531
|
-
if (typeof rules2 === "string") {
|
|
35532
|
-
rules2 = [rules2];
|
|
35533
|
-
}
|
|
35534
|
-
const providerOptions = {
|
|
35535
|
-
command: {
|
|
35536
|
-
onStarted(command) {
|
|
35537
|
-
console.log(`$ >>>> $ ${command}`);
|
|
35538
|
-
},
|
|
35539
|
-
onStdout(data) {
|
|
35540
|
-
process.stdout.write(data);
|
|
35541
|
-
},
|
|
35542
|
-
onStderr(data) {
|
|
35543
|
-
process.stderr.write(data);
|
|
35544
|
-
},
|
|
35545
|
-
onExit(code) {
|
|
35546
|
-
console.log(`$ <<<< $ Command exited with code: ${code}`);
|
|
35547
|
-
},
|
|
35548
|
-
onError(error) {
|
|
35549
|
-
console.log(`$ <<<< $ Command error: ${error}`);
|
|
35550
|
-
}
|
|
35551
|
-
},
|
|
35552
|
-
excludeFiles: options.config.excludeFiles
|
|
35553
|
-
};
|
|
35554
|
-
const platform = os.platform();
|
|
35555
|
-
const agents = [coderAgentInfo, architectAgentInfo];
|
|
35556
|
-
this.#multiAgent = new MultiAgent({
|
|
35557
|
-
createAgent: async (name) => {
|
|
35558
|
-
const agentName = name.trim().toLowerCase();
|
|
35559
|
-
switch (agentName) {
|
|
35560
|
-
case coderAgentInfo.name:
|
|
35561
|
-
return new CoderAgent({
|
|
35562
|
-
ai: service,
|
|
35563
|
-
os: platform,
|
|
35564
|
-
customInstructions: rules2,
|
|
35565
|
-
scripts: options.config.scripts,
|
|
35566
|
-
provider: getProvider("coder", options.config, providerOptions),
|
|
35567
|
-
interactive: options.interactive,
|
|
35568
|
-
agents
|
|
35569
|
-
});
|
|
35570
|
-
case architectAgentInfo.name:
|
|
35571
|
-
return new ArchitectAgent({
|
|
35572
|
-
ai: service,
|
|
35573
|
-
os: platform,
|
|
35574
|
-
customInstructions: rules2,
|
|
35575
|
-
scripts: options.config.scripts,
|
|
35576
|
-
provider: getProvider("architect", options.config, providerOptions),
|
|
35577
|
-
interactive: options.interactive,
|
|
35578
|
-
agents
|
|
35579
|
-
});
|
|
35580
|
-
case analyzerAgentInfo.name:
|
|
35581
|
-
return new AnalyzerAgent({
|
|
35582
|
-
ai: service,
|
|
35583
|
-
os: platform,
|
|
35584
|
-
customInstructions: rules2,
|
|
35585
|
-
scripts: options.config.scripts,
|
|
35586
|
-
provider: getProvider("analyzer", options.config, providerOptions),
|
|
35587
|
-
interactive: options.interactive,
|
|
35588
|
-
agents
|
|
35589
|
-
});
|
|
35590
|
-
default:
|
|
35591
|
-
throw new Error(`Unknown agent: ${name}`);
|
|
35592
|
-
}
|
|
35593
|
-
},
|
|
35594
|
-
getContext: async (name, context, files) => {
|
|
35595
|
-
let ret = await this.#defaultContext(name);
|
|
35596
|
-
const unreadableFiles = [];
|
|
35597
|
-
if (files) {
|
|
35598
|
-
for (const file of files) {
|
|
35599
|
-
try {
|
|
35600
|
-
const fileContent = await readFile2(file, "utf8");
|
|
35601
|
-
ret += `
|
|
35602
|
-
<file_content path="${file}">${fileContent}</file_content>`;
|
|
35603
|
-
} catch (error) {
|
|
35604
|
-
console.warn(`Failed to read file: ${file}`, error);
|
|
35605
|
-
unreadableFiles.push(file);
|
|
35606
|
-
}
|
|
35607
|
-
}
|
|
35608
|
-
if (unreadableFiles.length > 0) {
|
|
35609
|
-
ret += `
|
|
35610
|
-
<unreadable_files>
|
|
35611
|
-
`;
|
|
35612
|
-
for (const file of unreadableFiles) {
|
|
35613
|
-
ret += `${file}
|
|
35614
|
-
`;
|
|
35615
|
-
}
|
|
35616
|
-
ret += "</unreadable_files>";
|
|
35617
|
-
}
|
|
35618
|
-
}
|
|
35619
|
-
if (context) {
|
|
35620
|
-
ret += `
|
|
35621
|
-
|
|
35622
|
-
${context}`;
|
|
35623
|
-
}
|
|
35624
|
-
return ret;
|
|
35625
|
-
}
|
|
35626
|
-
});
|
|
35627
|
-
}
|
|
35628
|
-
async#defaultContext(name) {
|
|
35629
|
-
const cwd = process.cwd();
|
|
35630
|
-
const agentConfig = this.#options.config.agents?.[name] ?? this.#options.config.agents?.default ?? {};
|
|
35631
|
-
const maxFileCount = agentConfig.initialContext?.maxFileCount ?? 200;
|
|
35632
|
-
const excludes = agentConfig.initialContext?.excludes ?? [];
|
|
35633
|
-
const finalExcludes = excludes.concat(this.#options.config.excludeFiles ?? []);
|
|
35634
|
-
const [fileList, limited] = await listFiles(cwd, true, maxFileCount, cwd, finalExcludes);
|
|
35635
|
-
const fileContext = `<files>
|
|
35636
|
-
${fileList.join(`
|
|
35637
|
-
`)}${limited ? `
|
|
35638
|
-
<files_truncated>true</files_truncated>` : ""}
|
|
35639
|
-
</files>`;
|
|
35640
|
-
return `<now_date>${new Date().toISOString()}</now_date>${fileContext}`;
|
|
35641
|
-
}
|
|
35642
|
-
async startTask(task) {
|
|
35643
|
-
const agentName = architectAgentInfo.name;
|
|
35644
|
-
const [exitReason, info] = await this.#multiAgent.startTask({
|
|
35645
|
-
agentName,
|
|
35646
|
-
task,
|
|
35647
|
-
context: await this.#defaultContext(agentName),
|
|
35648
|
-
callback: this.#options.eventCallback
|
|
35649
|
-
});
|
|
35650
|
-
return [exitReason, info];
|
|
35651
|
-
}
|
|
35652
|
-
async continueTask(message, taskInfo) {
|
|
35653
|
-
return await this.#multiAgent.continueTask(message, taskInfo, this.#options.eventCallback);
|
|
35654
|
-
}
|
|
35655
|
-
get usage() {
|
|
35656
|
-
return this.#usageMeter.usage;
|
|
35657
|
-
}
|
|
35658
|
-
printUsage() {
|
|
35659
|
-
this.#usageMeter.printUsage();
|
|
35660
|
-
}
|
|
35661
|
-
}
|
|
35662
|
-
|
|
35663
35385
|
// ../../node_modules/@inquirer/core/dist/esm/lib/key.js
|
|
35664
35386
|
var isUpKey = (key) => key.name === "up" || key.name === "k" || key.ctrl && key.name === "p";
|
|
35665
35387
|
var isDownKey = (key) => key.name === "down" || key.name === "j" || key.ctrl && key.name === "n";
|
|
@@ -36220,15 +35942,15 @@ function useKeypress(userHandler) {
|
|
|
36220
35942
|
const signal = useRef(userHandler);
|
|
36221
35943
|
signal.current = userHandler;
|
|
36222
35944
|
useEffect((rl) => {
|
|
36223
|
-
let
|
|
35945
|
+
let ignore = false;
|
|
36224
35946
|
const handler13 = withUpdates((_input, event) => {
|
|
36225
|
-
if (
|
|
35947
|
+
if (ignore)
|
|
36226
35948
|
return;
|
|
36227
35949
|
signal.current(event, rl);
|
|
36228
35950
|
});
|
|
36229
35951
|
rl.input.on("keypress", handler13);
|
|
36230
35952
|
return () => {
|
|
36231
|
-
|
|
35953
|
+
ignore = true;
|
|
36232
35954
|
rl.input.removeListener("keypress", handler13);
|
|
36233
35955
|
};
|
|
36234
35956
|
}, []);
|
|
@@ -36583,11 +36305,11 @@ class ScreenManager {
|
|
|
36583
36305
|
render(content, bottomContent = "") {
|
|
36584
36306
|
const promptLine = lastLine(content);
|
|
36585
36307
|
const rawPromptLine = import_strip_ansi.default(promptLine);
|
|
36586
|
-
let
|
|
36308
|
+
let prompt5 = rawPromptLine;
|
|
36587
36309
|
if (this.rl.line.length > 0) {
|
|
36588
|
-
|
|
36310
|
+
prompt5 = prompt5.slice(0, -this.rl.line.length);
|
|
36589
36311
|
}
|
|
36590
|
-
this.rl.setPrompt(
|
|
36312
|
+
this.rl.setPrompt(prompt5);
|
|
36591
36313
|
this.cursorPos = this.rl.getCursorPos();
|
|
36592
36314
|
const width = readlineWidth();
|
|
36593
36315
|
content = breakLines(content, width);
|
|
@@ -36628,13 +36350,13 @@ class ScreenManager {
|
|
|
36628
36350
|
// ../../node_modules/@inquirer/core/dist/esm/lib/promise-polyfill.js
|
|
36629
36351
|
class PromisePolyfill extends Promise {
|
|
36630
36352
|
static withResolver() {
|
|
36631
|
-
let
|
|
36353
|
+
let resolve;
|
|
36632
36354
|
let reject;
|
|
36633
36355
|
const promise = new Promise((res, rej) => {
|
|
36634
|
-
|
|
36356
|
+
resolve = res;
|
|
36635
36357
|
reject = rej;
|
|
36636
36358
|
});
|
|
36637
|
-
return { promise, resolve
|
|
36359
|
+
return { promise, resolve, reject };
|
|
36638
36360
|
}
|
|
36639
36361
|
}
|
|
36640
36362
|
|
|
@@ -36657,7 +36379,7 @@ function getCallSites() {
|
|
|
36657
36379
|
function createPrompt(view) {
|
|
36658
36380
|
const callSites = getCallSites();
|
|
36659
36381
|
const callerFilename = callSites[1]?.getFileName?.();
|
|
36660
|
-
const
|
|
36382
|
+
const prompt5 = (config, context = {}) => {
|
|
36661
36383
|
const { input = process.stdin, signal } = context;
|
|
36662
36384
|
const cleanups = new Set;
|
|
36663
36385
|
const output = new import_mute_stream.default;
|
|
@@ -36668,7 +36390,7 @@ function createPrompt(view) {
|
|
|
36668
36390
|
output
|
|
36669
36391
|
});
|
|
36670
36392
|
const screen = new ScreenManager(rl);
|
|
36671
|
-
const { promise, resolve
|
|
36393
|
+
const { promise, resolve, reject } = PromisePolyfill.withResolver();
|
|
36672
36394
|
const cancel = () => reject(new CancelPromptError);
|
|
36673
36395
|
if (signal) {
|
|
36674
36396
|
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
@@ -36692,7 +36414,7 @@ function createPrompt(view) {
|
|
|
36692
36414
|
cycle(() => {
|
|
36693
36415
|
try {
|
|
36694
36416
|
const nextView = view(config, (value) => {
|
|
36695
|
-
setImmediate(() =>
|
|
36417
|
+
setImmediate(() => resolve(value));
|
|
36696
36418
|
});
|
|
36697
36419
|
if (nextView === undefined) {
|
|
36698
36420
|
throw new Error(`Prompt functions must return a string.
|
|
@@ -36718,7 +36440,7 @@ function createPrompt(view) {
|
|
|
36718
36440
|
}).then(() => promise), { cancel });
|
|
36719
36441
|
});
|
|
36720
36442
|
};
|
|
36721
|
-
return
|
|
36443
|
+
return prompt5;
|
|
36722
36444
|
}
|
|
36723
36445
|
// ../../node_modules/@inquirer/core/dist/esm/lib/Separator.js
|
|
36724
36446
|
var import_yoctocolors_cjs2 = __toESM(require_yoctocolors_cjs(), 1);
|
|
@@ -37030,6 +36752,376 @@ ${theme.style.description(selectedChoice.description)}` : ``;
|
|
|
37030
36752
|
return `${[prefix, message, helpTipTop].filter(Boolean).join(" ")}
|
|
37031
36753
|
${page}${helpTipBottom}${choiceDescription}${import_ansi_escapes3.default.cursorHide}`;
|
|
37032
36754
|
});
|
|
36755
|
+
// src/utils/listFiles.ts
|
|
36756
|
+
var import_ignore = __toESM(require_ignore(), 1);
|
|
36757
|
+
import { promises as fs2 } from "node:fs";
|
|
36758
|
+
import { join, relative, resolve } from "node:path";
|
|
36759
|
+
var DEFAULT_IGNORES = [
|
|
36760
|
+
"__pycache__",
|
|
36761
|
+
".DS_Store",
|
|
36762
|
+
".env",
|
|
36763
|
+
".git",
|
|
36764
|
+
".idea",
|
|
36765
|
+
".svn",
|
|
36766
|
+
".temp",
|
|
36767
|
+
".vscode",
|
|
36768
|
+
"coverage",
|
|
36769
|
+
"dist",
|
|
36770
|
+
"node_modules",
|
|
36771
|
+
"out",
|
|
36772
|
+
"Thumbs.db"
|
|
36773
|
+
];
|
|
36774
|
+
async function extendPatterns(basePatterns, dirPath) {
|
|
36775
|
+
try {
|
|
36776
|
+
const gitignorePath = join(dirPath, ".gitignore");
|
|
36777
|
+
const content = await fs2.readFile(gitignorePath, "utf8");
|
|
36778
|
+
const lines2 = content.split(/\r?\n/).filter(Boolean);
|
|
36779
|
+
return [...basePatterns, ...lines2];
|
|
36780
|
+
} catch {
|
|
36781
|
+
return basePatterns;
|
|
36782
|
+
}
|
|
36783
|
+
}
|
|
36784
|
+
function createIgnore(patterns) {
|
|
36785
|
+
return import_ignore.default().add(patterns);
|
|
36786
|
+
}
|
|
36787
|
+
async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles) {
|
|
36788
|
+
let rootPatterns = [...DEFAULT_IGNORES, ...excludeFiles || []];
|
|
36789
|
+
try {
|
|
36790
|
+
const rootGitignore = await fs2.readFile(join(cwd, ".gitignore"), "utf8");
|
|
36791
|
+
const lines2 = rootGitignore.split(/\r?\n/).filter(Boolean);
|
|
36792
|
+
rootPatterns = [...rootPatterns, ...lines2];
|
|
36793
|
+
} catch {
|
|
36794
|
+
}
|
|
36795
|
+
const results = [];
|
|
36796
|
+
const queue = [{ path: resolve(dirPath), patterns: rootPatterns }];
|
|
36797
|
+
while (queue.length > 0) {
|
|
36798
|
+
const { path: currentPath, patterns: parentPatterns } = queue.shift();
|
|
36799
|
+
const mergedPatterns = await extendPatterns(parentPatterns, currentPath);
|
|
36800
|
+
const folderIg = createIgnore(mergedPatterns);
|
|
36801
|
+
const entries = await fs2.readdir(currentPath, { withFileTypes: true });
|
|
36802
|
+
for (const entry of entries) {
|
|
36803
|
+
const fullPath = join(currentPath, entry.name);
|
|
36804
|
+
const relPath = relative(cwd, fullPath).replace(/\\/g, "/");
|
|
36805
|
+
if (folderIg.ignores(relPath)) {
|
|
36806
|
+
continue;
|
|
36807
|
+
}
|
|
36808
|
+
if (entry.isDirectory()) {
|
|
36809
|
+
if (recursive) {
|
|
36810
|
+
queue.push({ path: fullPath, patterns: mergedPatterns });
|
|
36811
|
+
}
|
|
36812
|
+
} else {
|
|
36813
|
+
results.push(relPath);
|
|
36814
|
+
if (results.length >= maxCount) {
|
|
36815
|
+
results.sort();
|
|
36816
|
+
return [results, true];
|
|
36817
|
+
}
|
|
36818
|
+
}
|
|
36819
|
+
}
|
|
36820
|
+
}
|
|
36821
|
+
results.sort();
|
|
36822
|
+
return [results, false];
|
|
36823
|
+
}
|
|
36824
|
+
|
|
36825
|
+
// src/utils/searchFiles.ts
|
|
36826
|
+
import { spawn } from "node:child_process";
|
|
36827
|
+
|
|
36828
|
+
// ../../node_modules/@vscode/ripgrep/lib/index.js
|
|
36829
|
+
var __dirname = "/Users/xiliangchen/projects/polka-codes/node_modules/@vscode/ripgrep/lib";
|
|
36830
|
+
var path = __require("path");
|
|
36831
|
+
var $rgPath = path.join(__dirname, `../bin/rg${process.platform === "win32" ? ".exe" : ""}`);
|
|
36832
|
+
|
|
36833
|
+
// src/utils/searchFiles.ts
|
|
36834
|
+
async function searchFiles(path2, regex, filePattern, cwd, excludeFiles) {
|
|
36835
|
+
const args = [
|
|
36836
|
+
"--line-number",
|
|
36837
|
+
"--context=5",
|
|
36838
|
+
"--color=never",
|
|
36839
|
+
"--with-filename",
|
|
36840
|
+
"--smart-case"
|
|
36841
|
+
];
|
|
36842
|
+
if (filePattern && filePattern !== "*") {
|
|
36843
|
+
args.push("--glob", filePattern);
|
|
36844
|
+
}
|
|
36845
|
+
if (excludeFiles) {
|
|
36846
|
+
for (const pattern of excludeFiles) {
|
|
36847
|
+
args.push("--ignore-file", pattern);
|
|
36848
|
+
}
|
|
36849
|
+
}
|
|
36850
|
+
args.push(regex, path2);
|
|
36851
|
+
return new Promise((resolve2, reject) => {
|
|
36852
|
+
const results = [];
|
|
36853
|
+
const rg = spawn($rgPath, args, {
|
|
36854
|
+
cwd,
|
|
36855
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
36856
|
+
});
|
|
36857
|
+
rg.stdout.on("data", (data) => {
|
|
36858
|
+
const lines2 = data.toString().split(`
|
|
36859
|
+
`).filter(Boolean);
|
|
36860
|
+
results.push(...lines2);
|
|
36861
|
+
});
|
|
36862
|
+
rg.stderr.on("data", (data) => {
|
|
36863
|
+
const err = data.toString();
|
|
36864
|
+
if (!err.startsWith("WARNING:")) {
|
|
36865
|
+
console.warn(err);
|
|
36866
|
+
}
|
|
36867
|
+
});
|
|
36868
|
+
rg.on("error", (error) => {
|
|
36869
|
+
reject(new Error(`Failed to execute ripgrep: ${error.message}`));
|
|
36870
|
+
});
|
|
36871
|
+
rg.on("close", (code) => {
|
|
36872
|
+
if (code !== 0 && code !== 1) {
|
|
36873
|
+
reject(new Error(`Ripgrep process exited with code ${code}`));
|
|
36874
|
+
return;
|
|
36875
|
+
}
|
|
36876
|
+
resolve2(results);
|
|
36877
|
+
});
|
|
36878
|
+
});
|
|
36879
|
+
}
|
|
36880
|
+
|
|
36881
|
+
// src/provider.ts
|
|
36882
|
+
var getProvider = (agentName, config, options = {}) => {
|
|
36883
|
+
const ig = import_ignore2.default().add(options.excludeFiles ?? []);
|
|
36884
|
+
const provider2 = {
|
|
36885
|
+
readFile: async (path2) => {
|
|
36886
|
+
if (ig.ignores(path2)) {
|
|
36887
|
+
throw new Error(`Not allow to access file ${path2}`);
|
|
36888
|
+
}
|
|
36889
|
+
return await readFile(path2, "utf8");
|
|
36890
|
+
},
|
|
36891
|
+
writeFile: async (path2, content) => {
|
|
36892
|
+
if (ig.ignores(path2)) {
|
|
36893
|
+
throw new Error(`Not allow to access file ${path2}`);
|
|
36894
|
+
}
|
|
36895
|
+
await mkdir(dirname(path2), { recursive: true });
|
|
36896
|
+
return await writeFile(path2, content, "utf8");
|
|
36897
|
+
},
|
|
36898
|
+
removeFile: async (path2) => {
|
|
36899
|
+
if (ig.ignores(path2)) {
|
|
36900
|
+
throw new Error(`Not allow to access file ${path2}`);
|
|
36901
|
+
}
|
|
36902
|
+
return await unlink(path2);
|
|
36903
|
+
},
|
|
36904
|
+
renameFile: async (sourcePath, targetPath) => {
|
|
36905
|
+
if (ig.ignores(sourcePath) || ig.ignores(targetPath)) {
|
|
36906
|
+
throw new Error(`Not allow to access file ${sourcePath} or ${targetPath}`);
|
|
36907
|
+
}
|
|
36908
|
+
return await rename(sourcePath, targetPath);
|
|
36909
|
+
},
|
|
36910
|
+
listFiles: async (path2, recursive, maxCount) => {
|
|
36911
|
+
return await listFiles(path2, recursive, maxCount, dirname(path2), options.excludeFiles);
|
|
36912
|
+
},
|
|
36913
|
+
searchFiles: async (path2, regex, filePattern) => {
|
|
36914
|
+
return await searchFiles(path2, regex, filePattern, dirname(path2), options.excludeFiles);
|
|
36915
|
+
},
|
|
36916
|
+
executeCommand: (command, needApprove) => {
|
|
36917
|
+
return new Promise((resolve2, reject) => {
|
|
36918
|
+
options.command?.onStarted(command);
|
|
36919
|
+
const child = spawn2(command, [], {
|
|
36920
|
+
shell: true,
|
|
36921
|
+
stdio: "pipe"
|
|
36922
|
+
});
|
|
36923
|
+
let stdoutText = "";
|
|
36924
|
+
let stderrText = "";
|
|
36925
|
+
child.stdout.on("data", (data) => {
|
|
36926
|
+
const dataStr = data.toString();
|
|
36927
|
+
options.command?.onStdout(dataStr);
|
|
36928
|
+
stdoutText += dataStr;
|
|
36929
|
+
});
|
|
36930
|
+
child.stderr.on("data", (data) => {
|
|
36931
|
+
const dataStr = data.toString();
|
|
36932
|
+
options.command?.onStderr(dataStr);
|
|
36933
|
+
stderrText += dataStr;
|
|
36934
|
+
});
|
|
36935
|
+
child.on("close", (code) => {
|
|
36936
|
+
options.command?.onExit(code ?? 0);
|
|
36937
|
+
resolve2({
|
|
36938
|
+
stdout: stdoutText,
|
|
36939
|
+
stderr: stderrText,
|
|
36940
|
+
exitCode: code ?? 0
|
|
36941
|
+
});
|
|
36942
|
+
});
|
|
36943
|
+
child.on("error", (err) => {
|
|
36944
|
+
options.command?.onError(err);
|
|
36945
|
+
reject(err);
|
|
36946
|
+
});
|
|
36947
|
+
});
|
|
36948
|
+
},
|
|
36949
|
+
askFollowupQuestion: async (question, answerOptions) => {
|
|
36950
|
+
if (options.interactive) {
|
|
36951
|
+
if (answerOptions.length === 0) {
|
|
36952
|
+
return await esm_default3({ message: question });
|
|
36953
|
+
}
|
|
36954
|
+
const otherMessage = "Other (enter text)";
|
|
36955
|
+
answerOptions.push(otherMessage);
|
|
36956
|
+
const answer = await esm_default5({
|
|
36957
|
+
message: question,
|
|
36958
|
+
choices: answerOptions.map((option) => ({ name: option, value: option }))
|
|
36959
|
+
});
|
|
36960
|
+
if (answer === otherMessage) {
|
|
36961
|
+
return await esm_default3({ message: "Enter your answer:" });
|
|
36962
|
+
}
|
|
36963
|
+
return answer;
|
|
36964
|
+
}
|
|
36965
|
+
return answerOptions[0] ?? "<warning>This is non-interactive mode, no answer can be provided.</warning>";
|
|
36966
|
+
},
|
|
36967
|
+
attemptCompletion: async (result) => {
|
|
36968
|
+
return;
|
|
36969
|
+
}
|
|
36970
|
+
};
|
|
36971
|
+
return provider2;
|
|
36972
|
+
};
|
|
36973
|
+
|
|
36974
|
+
// src/Runner.ts
|
|
36975
|
+
class Runner {
|
|
36976
|
+
#options;
|
|
36977
|
+
#multiAgent;
|
|
36978
|
+
#usageMeter;
|
|
36979
|
+
constructor(options) {
|
|
36980
|
+
this.#options = options;
|
|
36981
|
+
this.#usageMeter = new UsageMeter({
|
|
36982
|
+
maxCost: options.budget,
|
|
36983
|
+
maxMessageCount: options.maxMessageCount
|
|
36984
|
+
});
|
|
36985
|
+
const service = createService(options.provider, {
|
|
36986
|
+
apiKey: options.apiKey,
|
|
36987
|
+
model: options.model,
|
|
36988
|
+
usageMeter: this.#usageMeter,
|
|
36989
|
+
enableCache: options.enableCache
|
|
36990
|
+
});
|
|
36991
|
+
let rules2 = options.config.rules;
|
|
36992
|
+
if (typeof rules2 === "string") {
|
|
36993
|
+
rules2 = [rules2];
|
|
36994
|
+
}
|
|
36995
|
+
const providerOptions = {
|
|
36996
|
+
command: {
|
|
36997
|
+
onStarted(command) {
|
|
36998
|
+
console.log(`$ >>>> $ ${command}`);
|
|
36999
|
+
},
|
|
37000
|
+
onStdout(data) {
|
|
37001
|
+
process.stdout.write(data);
|
|
37002
|
+
},
|
|
37003
|
+
onStderr(data) {
|
|
37004
|
+
process.stderr.write(data);
|
|
37005
|
+
},
|
|
37006
|
+
onExit(code) {
|
|
37007
|
+
console.log(`$ <<<< $ Command exited with code: ${code}`);
|
|
37008
|
+
},
|
|
37009
|
+
onError(error) {
|
|
37010
|
+
console.log(`$ <<<< $ Command error: ${error}`);
|
|
37011
|
+
}
|
|
37012
|
+
},
|
|
37013
|
+
excludeFiles: options.config.excludeFiles,
|
|
37014
|
+
interactive: options.interactive
|
|
37015
|
+
};
|
|
37016
|
+
const platform = os.platform();
|
|
37017
|
+
const agents = [coderAgentInfo, architectAgentInfo];
|
|
37018
|
+
this.#multiAgent = new MultiAgent({
|
|
37019
|
+
createAgent: async (name) => {
|
|
37020
|
+
const agentName = name.trim().toLowerCase();
|
|
37021
|
+
switch (agentName) {
|
|
37022
|
+
case coderAgentInfo.name:
|
|
37023
|
+
return new CoderAgent({
|
|
37024
|
+
ai: service,
|
|
37025
|
+
os: platform,
|
|
37026
|
+
customInstructions: rules2,
|
|
37027
|
+
scripts: options.config.scripts,
|
|
37028
|
+
provider: getProvider("coder", options.config, providerOptions),
|
|
37029
|
+
interactive: options.interactive,
|
|
37030
|
+
agents
|
|
37031
|
+
});
|
|
37032
|
+
case architectAgentInfo.name:
|
|
37033
|
+
return new ArchitectAgent({
|
|
37034
|
+
ai: service,
|
|
37035
|
+
os: platform,
|
|
37036
|
+
customInstructions: rules2,
|
|
37037
|
+
scripts: options.config.scripts,
|
|
37038
|
+
provider: getProvider("architect", options.config, providerOptions),
|
|
37039
|
+
interactive: options.interactive,
|
|
37040
|
+
agents
|
|
37041
|
+
});
|
|
37042
|
+
case analyzerAgentInfo.name:
|
|
37043
|
+
return new AnalyzerAgent({
|
|
37044
|
+
ai: service,
|
|
37045
|
+
os: platform,
|
|
37046
|
+
customInstructions: rules2,
|
|
37047
|
+
scripts: options.config.scripts,
|
|
37048
|
+
provider: getProvider("analyzer", options.config, providerOptions),
|
|
37049
|
+
interactive: options.interactive,
|
|
37050
|
+
agents
|
|
37051
|
+
});
|
|
37052
|
+
default:
|
|
37053
|
+
throw new Error(`Unknown agent: ${name}`);
|
|
37054
|
+
}
|
|
37055
|
+
},
|
|
37056
|
+
getContext: async (name, context, files) => {
|
|
37057
|
+
let ret = await this.#defaultContext(name);
|
|
37058
|
+
const unreadableFiles = [];
|
|
37059
|
+
if (files) {
|
|
37060
|
+
for (const file of files) {
|
|
37061
|
+
try {
|
|
37062
|
+
const fileContent = await readFile2(file, "utf8");
|
|
37063
|
+
ret += `
|
|
37064
|
+
<file_content path="${file}">${fileContent}</file_content>`;
|
|
37065
|
+
} catch (error) {
|
|
37066
|
+
console.warn(`Failed to read file: ${file}`, error);
|
|
37067
|
+
unreadableFiles.push(file);
|
|
37068
|
+
}
|
|
37069
|
+
}
|
|
37070
|
+
if (unreadableFiles.length > 0) {
|
|
37071
|
+
ret += `
|
|
37072
|
+
<unreadable_files>
|
|
37073
|
+
`;
|
|
37074
|
+
for (const file of unreadableFiles) {
|
|
37075
|
+
ret += `${file}
|
|
37076
|
+
`;
|
|
37077
|
+
}
|
|
37078
|
+
ret += "</unreadable_files>";
|
|
37079
|
+
}
|
|
37080
|
+
}
|
|
37081
|
+
if (context) {
|
|
37082
|
+
ret += `
|
|
37083
|
+
|
|
37084
|
+
${context}`;
|
|
37085
|
+
}
|
|
37086
|
+
return ret;
|
|
37087
|
+
}
|
|
37088
|
+
});
|
|
37089
|
+
}
|
|
37090
|
+
async#defaultContext(name) {
|
|
37091
|
+
const cwd = process.cwd();
|
|
37092
|
+
const agentConfig = this.#options.config.agents?.[name] ?? this.#options.config.agents?.default ?? {};
|
|
37093
|
+
const maxFileCount = agentConfig.initialContext?.maxFileCount ?? 200;
|
|
37094
|
+
const excludes = agentConfig.initialContext?.excludes ?? [];
|
|
37095
|
+
const finalExcludes = excludes.concat(this.#options.config.excludeFiles ?? []);
|
|
37096
|
+
const [fileList, limited] = await listFiles(cwd, true, maxFileCount, cwd, finalExcludes);
|
|
37097
|
+
const fileContext = `<files>
|
|
37098
|
+
${fileList.join(`
|
|
37099
|
+
`)}${limited ? `
|
|
37100
|
+
<files_truncated>true</files_truncated>` : ""}
|
|
37101
|
+
</files>`;
|
|
37102
|
+
return `<now_date>${new Date().toISOString()}</now_date>${fileContext}`;
|
|
37103
|
+
}
|
|
37104
|
+
async startTask(task) {
|
|
37105
|
+
const agentName = architectAgentInfo.name;
|
|
37106
|
+
const [exitReason, info] = await this.#multiAgent.startTask({
|
|
37107
|
+
agentName,
|
|
37108
|
+
task,
|
|
37109
|
+
context: await this.#defaultContext(agentName),
|
|
37110
|
+
callback: this.#options.eventCallback
|
|
37111
|
+
});
|
|
37112
|
+
return [exitReason, info];
|
|
37113
|
+
}
|
|
37114
|
+
async continueTask(message, taskInfo) {
|
|
37115
|
+
return await this.#multiAgent.continueTask(message, taskInfo, this.#options.eventCallback);
|
|
37116
|
+
}
|
|
37117
|
+
get usage() {
|
|
37118
|
+
return this.#usageMeter.usage;
|
|
37119
|
+
}
|
|
37120
|
+
printUsage() {
|
|
37121
|
+
this.#usageMeter.printUsage();
|
|
37122
|
+
}
|
|
37123
|
+
}
|
|
37124
|
+
|
|
37033
37125
|
// src/configPrompt.ts
|
|
37034
37126
|
var fetchOllamaModels = async () => {
|
|
37035
37127
|
try {
|
|
@@ -41888,6 +41980,10 @@ ${event.systemPrompt}`);
|
|
|
41888
41980
|
var runChat = async (opts, command) => {
|
|
41889
41981
|
const options = command?.parent?.opts() ?? opts ?? {};
|
|
41890
41982
|
const { config, providerConfig, maxMessageCount, verbose, budget } = parseOptions(options);
|
|
41983
|
+
if (!process.stdin.isTTY) {
|
|
41984
|
+
console.error("Error: Terminal is not interactive. Please run this command in an interactive terminal.");
|
|
41985
|
+
process.exit(1);
|
|
41986
|
+
}
|
|
41891
41987
|
let { provider: provider2, model, apiKey } = providerConfig.getConfigForAgent("coder") ?? {};
|
|
41892
41988
|
if (!provider2) {
|
|
41893
41989
|
const newConfig = await configPrompt({ provider: provider2, model, apiKey });
|
|
@@ -42613,8 +42709,8 @@ ${result.response}`);
|
|
|
42613
42709
|
});
|
|
42614
42710
|
|
|
42615
42711
|
// src/commands/init.ts
|
|
42616
|
-
import os4 from "node:os";
|
|
42617
42712
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
42713
|
+
import os4 from "node:os";
|
|
42618
42714
|
import { dirname as dirname2 } from "node:path";
|
|
42619
42715
|
var import_lodash3 = __toESM(require_lodash(), 1);
|
|
42620
42716
|
var initCommand = new Command("init").description("Initialize polkacodes configuration").option("-g, --global", "Use global config");
|
|
@@ -42852,48 +42948,77 @@ var prCommand = new Command("pr").description("Create a GitHub pull request").ar
|
|
|
42852
42948
|
});
|
|
42853
42949
|
|
|
42854
42950
|
// src/commands/task.ts
|
|
42855
|
-
async
|
|
42856
|
-
|
|
42857
|
-
|
|
42951
|
+
var readStdin = async (timeoutMs = 30000) => {
|
|
42952
|
+
if (process.stdin.isTTY) {
|
|
42953
|
+
return "";
|
|
42954
|
+
}
|
|
42955
|
+
return new Promise((resolve2, reject) => {
|
|
42956
|
+
let input = "";
|
|
42957
|
+
let timeoutId = undefined;
|
|
42958
|
+
const cleanup = () => {
|
|
42959
|
+
if (timeoutId)
|
|
42960
|
+
clearTimeout(timeoutId);
|
|
42961
|
+
process.stdin.removeAllListeners();
|
|
42962
|
+
process.stdin.resume();
|
|
42963
|
+
};
|
|
42964
|
+
timeoutId = setTimeout(() => {
|
|
42965
|
+
cleanup();
|
|
42966
|
+
reject(new Error("Stdin read timeout"));
|
|
42967
|
+
}, timeoutMs);
|
|
42968
|
+
process.stdin.on("data", (chunk) => {
|
|
42969
|
+
input += chunk.toString();
|
|
42970
|
+
});
|
|
42971
|
+
process.stdin.on("end", () => {
|
|
42972
|
+
cleanup();
|
|
42973
|
+
if (!input) {
|
|
42974
|
+
reject(new Error("Empty stdin input"));
|
|
42975
|
+
return;
|
|
42976
|
+
}
|
|
42977
|
+
resolve2(input);
|
|
42978
|
+
});
|
|
42979
|
+
process.stdin.on("error", (err) => {
|
|
42980
|
+
cleanup();
|
|
42981
|
+
reject(err);
|
|
42982
|
+
});
|
|
42983
|
+
});
|
|
42984
|
+
};
|
|
42985
|
+
async function runTask(taskArg, _options, command) {
|
|
42986
|
+
let task = taskArg;
|
|
42987
|
+
if (!task) {
|
|
42988
|
+
try {
|
|
42989
|
+
const stdinInput = await readStdin();
|
|
42990
|
+
if (stdinInput) {
|
|
42991
|
+
task = stdinInput;
|
|
42992
|
+
} else {
|
|
42993
|
+
runChat({}, command);
|
|
42994
|
+
return;
|
|
42995
|
+
}
|
|
42996
|
+
} catch (error) {
|
|
42997
|
+
console.error("Error reading stdin:", error);
|
|
42998
|
+
process.exit(1);
|
|
42999
|
+
}
|
|
43000
|
+
}
|
|
43001
|
+
const { config, providerConfig, verbose, maxMessageCount, budget } = parseOptions(command.opts());
|
|
43002
|
+
const { provider: provider2, model, apiKey } = providerConfig.getConfigForAgent("architect") ?? {};
|
|
42858
43003
|
if (!provider2 || !model) {
|
|
42859
43004
|
console.error("Provider and model must be configured");
|
|
42860
43005
|
process.exit(1);
|
|
42861
43006
|
}
|
|
42862
|
-
|
|
42863
|
-
|
|
42864
|
-
return;
|
|
42865
|
-
}
|
|
43007
|
+
console.log("Provider:", provider2);
|
|
43008
|
+
console.log("Model:", model);
|
|
42866
43009
|
const runner = new Runner({
|
|
42867
43010
|
provider: provider2,
|
|
42868
43011
|
model,
|
|
42869
43012
|
apiKey,
|
|
42870
43013
|
config,
|
|
42871
|
-
maxMessageCount
|
|
42872
|
-
budget
|
|
42873
|
-
interactive:
|
|
42874
|
-
eventCallback: printEvent(
|
|
43014
|
+
maxMessageCount,
|
|
43015
|
+
budget,
|
|
43016
|
+
interactive: process.stdin.isTTY,
|
|
43017
|
+
eventCallback: printEvent(verbose),
|
|
42875
43018
|
enableCache: true
|
|
42876
43019
|
});
|
|
42877
|
-
|
|
42878
|
-
|
|
42879
|
-
switch (exitReason.type) {
|
|
42880
|
-
case "UsageExceeded":
|
|
42881
|
-
console.error("Task failed: Usage limit exceeded");
|
|
42882
|
-
process.exit(1);
|
|
42883
|
-
break;
|
|
42884
|
-
case "WaitForUserInput":
|
|
42885
|
-
break;
|
|
42886
|
-
case "Exit" /* Exit */:
|
|
42887
|
-
break;
|
|
42888
|
-
case "Interrupted" /* Interrupted */:
|
|
42889
|
-
console.error("Task interrupted:", exitReason.message);
|
|
42890
|
-
process.exit(1);
|
|
42891
|
-
break;
|
|
42892
|
-
case "HandOver" /* HandOver */:
|
|
42893
|
-
break;
|
|
42894
|
-
}
|
|
42895
|
-
runner.printUsage();
|
|
42896
|
-
}
|
|
43020
|
+
await runner.startTask(task);
|
|
43021
|
+
runner.printUsage();
|
|
42897
43022
|
}
|
|
42898
43023
|
|
|
42899
43024
|
// src/index.ts
|