@polka-codes/cli 0.4.4 → 0.4.6
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 +3 -4
- package/dist/index.js +419 -44
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -77,12 +77,11 @@ rules: |
|
|
|
77
77
|
|
|
78
78
|
### AI Configuration
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Supported providers (in recommended order):
|
|
80
|
+
Supported providers
|
|
83
81
|
1. DeepSeek / `deepseek` (recommended)
|
|
84
82
|
2. Anthropic / `anthropic` (Sonnet 3.5 recommended)
|
|
85
|
-
3.
|
|
83
|
+
3. OpenRouter / `openrouter`
|
|
84
|
+
4. Ollama / `ollama`
|
|
86
85
|
|
|
87
86
|
Configure the AI service by creating a `.env` file in your project root:
|
|
88
87
|
|
package/dist/index.js
CHANGED
|
@@ -24629,7 +24629,7 @@ var {
|
|
|
24629
24629
|
Help
|
|
24630
24630
|
} = import__.default;
|
|
24631
24631
|
// package.json
|
|
24632
|
-
var version = "0.4.
|
|
24632
|
+
var version = "0.4.6";
|
|
24633
24633
|
|
|
24634
24634
|
// ../../node_modules/@anthropic-ai/sdk/version.mjs
|
|
24635
24635
|
var VERSION = "0.36.2";
|
|
@@ -32890,17 +32890,169 @@ class OllamaService extends AiServiceBase {
|
|
|
32890
32890
|
}
|
|
32891
32891
|
}
|
|
32892
32892
|
|
|
32893
|
+
// ../core/src/AiService/OpenRouterService.ts
|
|
32894
|
+
class OpenRouterService extends AiServiceBase {
|
|
32895
|
+
#client;
|
|
32896
|
+
#apiKey;
|
|
32897
|
+
model;
|
|
32898
|
+
constructor(options) {
|
|
32899
|
+
super();
|
|
32900
|
+
if (!options.model) {
|
|
32901
|
+
throw new Error("OpenRouter requires a model");
|
|
32902
|
+
}
|
|
32903
|
+
if (!options.apiKey) {
|
|
32904
|
+
throw new Error("OpenRouter requires an API key");
|
|
32905
|
+
}
|
|
32906
|
+
this.#apiKey = options.apiKey;
|
|
32907
|
+
this.#client = new openai_default({
|
|
32908
|
+
baseURL: "https://openrouter.ai/api/v1",
|
|
32909
|
+
apiKey: options.apiKey,
|
|
32910
|
+
defaultHeaders: {
|
|
32911
|
+
"HTTP-Referer": "https://polka.codes",
|
|
32912
|
+
"X-Title": "Polka Codes"
|
|
32913
|
+
}
|
|
32914
|
+
});
|
|
32915
|
+
this.model = {
|
|
32916
|
+
id: options.model,
|
|
32917
|
+
info: {}
|
|
32918
|
+
};
|
|
32919
|
+
}
|
|
32920
|
+
async* send(systemPrompt, messages) {
|
|
32921
|
+
const openAiMessages = [
|
|
32922
|
+
{ role: "system", content: systemPrompt },
|
|
32923
|
+
...convertToOpenAiMessages(messages)
|
|
32924
|
+
];
|
|
32925
|
+
switch (this.model.id) {
|
|
32926
|
+
case "anthropic/claude-3.5-sonnet":
|
|
32927
|
+
case "anthropic/claude-3.5-sonnet:beta":
|
|
32928
|
+
case "anthropic/claude-3.5-sonnet-20240620":
|
|
32929
|
+
case "anthropic/claude-3.5-sonnet-20240620:beta":
|
|
32930
|
+
case "anthropic/claude-3-5-haiku":
|
|
32931
|
+
case "anthropic/claude-3-5-haiku:beta":
|
|
32932
|
+
case "anthropic/claude-3-5-haiku-20241022":
|
|
32933
|
+
case "anthropic/claude-3-5-haiku-20241022:beta":
|
|
32934
|
+
case "anthropic/claude-3-haiku":
|
|
32935
|
+
case "anthropic/claude-3-haiku:beta":
|
|
32936
|
+
case "anthropic/claude-3-opus":
|
|
32937
|
+
case "anthropic/claude-3-opus:beta": {
|
|
32938
|
+
openAiMessages[0] = {
|
|
32939
|
+
role: "system",
|
|
32940
|
+
content: [
|
|
32941
|
+
{
|
|
32942
|
+
type: "text",
|
|
32943
|
+
text: systemPrompt,
|
|
32944
|
+
cache_control: { type: "ephemeral" }
|
|
32945
|
+
}
|
|
32946
|
+
]
|
|
32947
|
+
};
|
|
32948
|
+
const lastTwoUserMessages = openAiMessages.filter((msg) => msg.role === "user").slice(-2);
|
|
32949
|
+
for (const msg of lastTwoUserMessages) {
|
|
32950
|
+
if (typeof msg.content === "string") {
|
|
32951
|
+
msg.content = [{ type: "text", text: msg.content }];
|
|
32952
|
+
}
|
|
32953
|
+
if (Array.isArray(msg.content)) {
|
|
32954
|
+
let lastTextPart = msg.content.filter((part) => part.type === "text").pop();
|
|
32955
|
+
if (!lastTextPart) {
|
|
32956
|
+
lastTextPart = { type: "text", text: "..." };
|
|
32957
|
+
msg.content.push(lastTextPart);
|
|
32958
|
+
}
|
|
32959
|
+
lastTextPart.cache_control = { type: "ephemeral" };
|
|
32960
|
+
}
|
|
32961
|
+
}
|
|
32962
|
+
break;
|
|
32963
|
+
}
|
|
32964
|
+
default:
|
|
32965
|
+
break;
|
|
32966
|
+
}
|
|
32967
|
+
let maxTokens;
|
|
32968
|
+
switch (this.model.id) {
|
|
32969
|
+
case "anthropic/claude-3.5-sonnet":
|
|
32970
|
+
case "anthropic/claude-3.5-sonnet:beta":
|
|
32971
|
+
case "anthropic/claude-3.5-sonnet-20240620":
|
|
32972
|
+
case "anthropic/claude-3.5-sonnet-20240620:beta":
|
|
32973
|
+
case "anthropic/claude-3-5-haiku":
|
|
32974
|
+
case "anthropic/claude-3-5-haiku:beta":
|
|
32975
|
+
case "anthropic/claude-3-5-haiku-20241022":
|
|
32976
|
+
case "anthropic/claude-3-5-haiku-20241022:beta":
|
|
32977
|
+
maxTokens = 8192;
|
|
32978
|
+
break;
|
|
32979
|
+
}
|
|
32980
|
+
let shouldApplyMiddleOutTransform = !this.model.info.supportsPromptCache;
|
|
32981
|
+
if (this.model.id === "deepseek/deepseek-chat") {
|
|
32982
|
+
shouldApplyMiddleOutTransform = true;
|
|
32983
|
+
}
|
|
32984
|
+
const stream = await this.#client.chat.completions.create({
|
|
32985
|
+
model: this.model.id,
|
|
32986
|
+
max_completion_tokens: maxTokens,
|
|
32987
|
+
messages: openAiMessages,
|
|
32988
|
+
temperature: 0,
|
|
32989
|
+
stream: true,
|
|
32990
|
+
transforms: shouldApplyMiddleOutTransform ? ["middle-out"] : undefined,
|
|
32991
|
+
include_reasoning: true
|
|
32992
|
+
});
|
|
32993
|
+
let genId;
|
|
32994
|
+
for await (const chunk of stream) {
|
|
32995
|
+
if ("error" in chunk) {
|
|
32996
|
+
const error = chunk.error;
|
|
32997
|
+
console.error(`OpenRouter API Error: ${error?.code} - ${error?.message}`);
|
|
32998
|
+
throw new Error(`OpenRouter API Error ${error?.code}: ${error?.message}`);
|
|
32999
|
+
}
|
|
33000
|
+
if (!genId && chunk.id) {
|
|
33001
|
+
genId = chunk.id;
|
|
33002
|
+
}
|
|
33003
|
+
const delta = chunk.choices[0]?.delta;
|
|
33004
|
+
if (delta?.reasoning) {
|
|
33005
|
+
yield {
|
|
33006
|
+
type: "reasoning",
|
|
33007
|
+
text: delta.reasoning
|
|
33008
|
+
};
|
|
33009
|
+
}
|
|
33010
|
+
if (delta?.content) {
|
|
33011
|
+
yield {
|
|
33012
|
+
type: "text",
|
|
33013
|
+
text: delta.content
|
|
33014
|
+
};
|
|
33015
|
+
}
|
|
33016
|
+
}
|
|
33017
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
33018
|
+
const controller = new AbortController;
|
|
33019
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
33020
|
+
try {
|
|
33021
|
+
const response = await fetch(`https://openrouter.ai/api/v1/generation?id=${genId}`, {
|
|
33022
|
+
headers: {
|
|
33023
|
+
Authorization: `Bearer ${this.#apiKey}`
|
|
33024
|
+
},
|
|
33025
|
+
signal: controller.signal
|
|
33026
|
+
});
|
|
33027
|
+
const responseBody = await response.json();
|
|
33028
|
+
const generation = responseBody.data;
|
|
33029
|
+
yield {
|
|
33030
|
+
type: "usage",
|
|
33031
|
+
inputTokens: generation?.native_tokens_prompt || 0,
|
|
33032
|
+
outputTokens: generation?.native_tokens_completion || 0,
|
|
33033
|
+
totalCost: generation?.total_cost || 0
|
|
33034
|
+
};
|
|
33035
|
+
} catch (error) {
|
|
33036
|
+
console.error("Error fetching OpenRouter generation details:", error);
|
|
33037
|
+
} finally {
|
|
33038
|
+
clearTimeout(timeout);
|
|
33039
|
+
}
|
|
33040
|
+
}
|
|
33041
|
+
}
|
|
33042
|
+
|
|
32893
33043
|
// ../core/src/AiService/index.ts
|
|
32894
33044
|
var AiServiceProvider;
|
|
32895
33045
|
((AiServiceProvider2) => {
|
|
32896
33046
|
AiServiceProvider2["Anthropic"] = "anthropic";
|
|
32897
33047
|
AiServiceProvider2["Ollama"] = "ollama";
|
|
32898
33048
|
AiServiceProvider2["DeepSeek"] = "deepseek";
|
|
33049
|
+
AiServiceProvider2["OpenRouter"] = "openrouter";
|
|
32899
33050
|
})(AiServiceProvider ||= {});
|
|
32900
33051
|
var defaultModels = {
|
|
32901
33052
|
["anthropic" /* Anthropic */]: "claude-3-5-sonnet-20241022",
|
|
32902
33053
|
["ollama" /* Ollama */]: "maryasov/qwen2.5-coder-cline:7b",
|
|
32903
|
-
["deepseek" /* DeepSeek */]: "deepseek-chat"
|
|
33054
|
+
["deepseek" /* DeepSeek */]: "deepseek-chat",
|
|
33055
|
+
["openrouter" /* OpenRouter */]: "anthropic/claude-3.5-sonnet"
|
|
32904
33056
|
};
|
|
32905
33057
|
var createService = (provider, options) => {
|
|
32906
33058
|
switch (provider) {
|
|
@@ -32910,6 +33062,8 @@ var createService = (provider, options) => {
|
|
|
32910
33062
|
return new OllamaService(options);
|
|
32911
33063
|
case "deepseek" /* DeepSeek */:
|
|
32912
33064
|
return new DeepSeekService(options);
|
|
33065
|
+
case "openrouter" /* OpenRouter */:
|
|
33066
|
+
return new OpenRouterService(options);
|
|
32913
33067
|
}
|
|
32914
33068
|
};
|
|
32915
33069
|
// ../core/src/tool.ts
|
|
@@ -33086,12 +33240,8 @@ var capabilities = (toolNamePrefix) => `
|
|
|
33086
33240
|
|
|
33087
33241
|
CAPABILITIES
|
|
33088
33242
|
|
|
33089
|
-
- You have access to a range of tools to aid you in your work. These tools help you effectively accomplish a wide range of tasks
|
|
33090
|
-
- When the user initially gives you a task, a recursive list of all filepaths in the current working directory will be included in
|
|
33091
|
-
- You can use ${toolNamePrefix}search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring.
|
|
33092
|
-
- You can use the ${toolNamePrefix}list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task.
|
|
33093
|
-
\t- For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use ${toolNamePrefix}list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then ${toolNamePrefix}read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the ${toolNamePrefix}replace_in_file tool to implement changes. If you refactored code that could affect other parts of the codebase, you could use ${toolNamePrefix}search_files to ensure you update other files as needed.
|
|
33094
|
-
- You can use the ${toolNamePrefix}execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance.`;
|
|
33243
|
+
- You have access to a range of tools to aid you in your work. These tools help you effectively accomplish a wide range of tasks.
|
|
33244
|
+
- When the user initially gives you a task, a recursive list of all filepaths in the current working directory will be included in context. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further.`;
|
|
33095
33245
|
var systemInformation = (info) => `
|
|
33096
33246
|
====
|
|
33097
33247
|
|
|
@@ -33156,7 +33306,7 @@ ${joined}`;
|
|
|
33156
33306
|
};
|
|
33157
33307
|
var responsePrompts = {
|
|
33158
33308
|
errorInvokeTool: (tool, error) => `An error occurred while invoking the tool "${tool}": ${error}`,
|
|
33159
|
-
requireUseTool: "Error: You must use a tool before proceeding",
|
|
33309
|
+
requireUseTool: "Error: You must use a tool before proceeding. Making sure the tool is invoked using xml tags.",
|
|
33160
33310
|
toolResults: (tool, result) => `<tool_response>
|
|
33161
33311
|
<tool_name>${tool}</tool_name>
|
|
33162
33312
|
<tool_result>
|
|
@@ -33191,6 +33341,9 @@ ${agents}`;
|
|
|
33191
33341
|
callback = () => {
|
|
33192
33342
|
}
|
|
33193
33343
|
}) {
|
|
33344
|
+
if (maxIterations < 1) {
|
|
33345
|
+
throw new Error("Max iterations must be greater than 0");
|
|
33346
|
+
}
|
|
33194
33347
|
const taskInfo = {
|
|
33195
33348
|
options: {
|
|
33196
33349
|
maxIterations
|
|
@@ -33207,6 +33360,7 @@ ${agents}`;
|
|
|
33207
33360
|
text += `
|
|
33208
33361
|
<context>${context}</context>`;
|
|
33209
33362
|
}
|
|
33363
|
+
callback({ kind: "StartTask" /* StartTask */, info: taskInfo, systemPrompt: this.config.systemPrompt });
|
|
33210
33364
|
return await this.#processLoop(text, taskInfo, callback);
|
|
33211
33365
|
}
|
|
33212
33366
|
async#processLoop(userMessage, taskInfo, callback) {
|
|
@@ -33350,6 +33504,8 @@ __export(exports_allTools, {
|
|
|
33350
33504
|
writeToFile: () => writeToFile_default,
|
|
33351
33505
|
searchFiles: () => searchFiles_default,
|
|
33352
33506
|
replaceInFile: () => replaceInFile_default,
|
|
33507
|
+
renameFile: () => renameFile_default,
|
|
33508
|
+
removeFile: () => removeFile_default,
|
|
33353
33509
|
readFile: () => readFile_default,
|
|
33354
33510
|
listFiles: () => listFiles_default,
|
|
33355
33511
|
listCodeDefinitionNames: () => listCodeDefinitionNames_default,
|
|
@@ -33430,7 +33586,10 @@ var getStringArray = (args, name, defaultValue) => {
|
|
|
33430
33586
|
}
|
|
33431
33587
|
return defaultValue;
|
|
33432
33588
|
}
|
|
33433
|
-
|
|
33589
|
+
if (ret === "") {
|
|
33590
|
+
return [];
|
|
33591
|
+
}
|
|
33592
|
+
return ret.split(",").map((s2) => s2.trim());
|
|
33434
33593
|
};
|
|
33435
33594
|
var getBoolean = (args, name, defaultValue) => {
|
|
33436
33595
|
const ret = args[name];
|
|
@@ -34062,7 +34221,7 @@ var handler9 = async (provider, args) => {
|
|
|
34062
34221
|
await provider.writeFile(path, content);
|
|
34063
34222
|
return {
|
|
34064
34223
|
type: "Reply" /* Reply */,
|
|
34065
|
-
message: `<
|
|
34224
|
+
message: `<write_to_file_path>${path}</write_to_file_path><status>Success</status>`
|
|
34066
34225
|
};
|
|
34067
34226
|
};
|
|
34068
34227
|
var isAvailable9 = (provider) => {
|
|
@@ -34099,7 +34258,7 @@ var toolInfo10 = {
|
|
|
34099
34258
|
{
|
|
34100
34259
|
name: "files",
|
|
34101
34260
|
description: "The files relevant to the task",
|
|
34102
|
-
required:
|
|
34261
|
+
required: false,
|
|
34103
34262
|
usageValue: "Relevant files"
|
|
34104
34263
|
}
|
|
34105
34264
|
],
|
|
@@ -34148,6 +34307,109 @@ var handOver_default = {
|
|
|
34148
34307
|
handler: handler10,
|
|
34149
34308
|
isAvailable: isAvailable10
|
|
34150
34309
|
};
|
|
34310
|
+
// ../core/src/tools/removeFile.ts
|
|
34311
|
+
var toolInfo11 = {
|
|
34312
|
+
name: "remove_file",
|
|
34313
|
+
description: "Request to remove a file at the specified path.",
|
|
34314
|
+
parameters: [
|
|
34315
|
+
{
|
|
34316
|
+
name: "path",
|
|
34317
|
+
description: "The path of the file to remove",
|
|
34318
|
+
required: true,
|
|
34319
|
+
usageValue: "File path here"
|
|
34320
|
+
}
|
|
34321
|
+
],
|
|
34322
|
+
examples: [
|
|
34323
|
+
{
|
|
34324
|
+
description: "Request to remove a file",
|
|
34325
|
+
parameters: [
|
|
34326
|
+
{
|
|
34327
|
+
name: "path",
|
|
34328
|
+
value: "src/main.js"
|
|
34329
|
+
}
|
|
34330
|
+
]
|
|
34331
|
+
}
|
|
34332
|
+
]
|
|
34333
|
+
};
|
|
34334
|
+
var handler11 = async (provider, args) => {
|
|
34335
|
+
if (!provider.removeFile) {
|
|
34336
|
+
return {
|
|
34337
|
+
type: "Error" /* Error */,
|
|
34338
|
+
message: "Not possible to remove file. Abort."
|
|
34339
|
+
};
|
|
34340
|
+
}
|
|
34341
|
+
const path = getString(args, "path");
|
|
34342
|
+
await provider.removeFile(path);
|
|
34343
|
+
return {
|
|
34344
|
+
type: "Reply" /* Reply */,
|
|
34345
|
+
message: `<remove_file_path>${path}</remove_file_path><status>Success</status>`
|
|
34346
|
+
};
|
|
34347
|
+
};
|
|
34348
|
+
var isAvailable11 = (provider) => {
|
|
34349
|
+
return !!provider.removeFile;
|
|
34350
|
+
};
|
|
34351
|
+
var removeFile_default = {
|
|
34352
|
+
...toolInfo11,
|
|
34353
|
+
handler: handler11,
|
|
34354
|
+
isAvailable: isAvailable11
|
|
34355
|
+
};
|
|
34356
|
+
// ../core/src/tools/renameFile.ts
|
|
34357
|
+
var toolInfo12 = {
|
|
34358
|
+
name: "rename_file",
|
|
34359
|
+
description: "Request to rename a file from source path to target path.",
|
|
34360
|
+
parameters: [
|
|
34361
|
+
{
|
|
34362
|
+
name: "sourcePath",
|
|
34363
|
+
description: "The current path of the file",
|
|
34364
|
+
required: true,
|
|
34365
|
+
usageValue: "Source file path here"
|
|
34366
|
+
},
|
|
34367
|
+
{
|
|
34368
|
+
name: "targetPath",
|
|
34369
|
+
description: "The new path for the file",
|
|
34370
|
+
required: true,
|
|
34371
|
+
usageValue: "Target file path here"
|
|
34372
|
+
}
|
|
34373
|
+
],
|
|
34374
|
+
examples: [
|
|
34375
|
+
{
|
|
34376
|
+
description: "Request to rename a file",
|
|
34377
|
+
parameters: [
|
|
34378
|
+
{
|
|
34379
|
+
name: "sourcePath",
|
|
34380
|
+
value: "src/old-name.js"
|
|
34381
|
+
},
|
|
34382
|
+
{
|
|
34383
|
+
name: "targetPath",
|
|
34384
|
+
value: "src/new-name.js"
|
|
34385
|
+
}
|
|
34386
|
+
]
|
|
34387
|
+
}
|
|
34388
|
+
]
|
|
34389
|
+
};
|
|
34390
|
+
var handler12 = async (provider, args) => {
|
|
34391
|
+
if (!provider.renameFile) {
|
|
34392
|
+
return {
|
|
34393
|
+
type: "Error" /* Error */,
|
|
34394
|
+
message: "Not possible to rename file. Abort."
|
|
34395
|
+
};
|
|
34396
|
+
}
|
|
34397
|
+
const sourcePath = getString(args, "sourcePath");
|
|
34398
|
+
const targetPath = getString(args, "targetPath");
|
|
34399
|
+
await provider.renameFile(sourcePath, targetPath);
|
|
34400
|
+
return {
|
|
34401
|
+
type: "Reply" /* Reply */,
|
|
34402
|
+
message: `<rename_file_path>${targetPath}</rename_file_path><status>Success</status>`
|
|
34403
|
+
};
|
|
34404
|
+
};
|
|
34405
|
+
var isAvailable12 = (provider) => {
|
|
34406
|
+
return !!provider.renameFile;
|
|
34407
|
+
};
|
|
34408
|
+
var renameFile_default = {
|
|
34409
|
+
...toolInfo12,
|
|
34410
|
+
handler: handler12,
|
|
34411
|
+
isAvailable: isAvailable12
|
|
34412
|
+
};
|
|
34151
34413
|
// ../core/src/Agent/CoderAgent/prompts.ts
|
|
34152
34414
|
var basePrompt = "You are a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.";
|
|
34153
34415
|
var editingFilesPrompt = (toolNamePrefix) => `
|
|
@@ -34392,19 +34654,24 @@ class MultiAgent {
|
|
|
34392
34654
|
get model() {
|
|
34393
34655
|
return this.#activeAgent?.model;
|
|
34394
34656
|
}
|
|
34395
|
-
async#startTask(agentName, task, context, callback) {
|
|
34657
|
+
async#startTask(agentName, task, context, maxIterations, callback) {
|
|
34396
34658
|
this.#activeAgent = await this.#config.createAgent(agentName);
|
|
34397
34659
|
const [exitReason, info] = await this.#activeAgent.startTask({
|
|
34398
34660
|
task,
|
|
34399
34661
|
context,
|
|
34662
|
+
maxIterations,
|
|
34400
34663
|
callback
|
|
34401
34664
|
});
|
|
34402
34665
|
if (typeof exitReason === "string") {
|
|
34403
34666
|
return [exitReason, info];
|
|
34404
34667
|
}
|
|
34405
34668
|
if (exitReason.type === "HandOver") {
|
|
34669
|
+
const remainIteration = maxIterations - Math.floor(info.messages.length / 2);
|
|
34670
|
+
if (remainIteration < 1) {
|
|
34671
|
+
return ["MaxIterations", info];
|
|
34672
|
+
}
|
|
34406
34673
|
const context2 = await this.#config.getContext(agentName, exitReason.context, exitReason.files);
|
|
34407
|
-
const [exitReason2, info2] = await this.#startTask(exitReason.agentName, exitReason.task, context2, callback);
|
|
34674
|
+
const [exitReason2, info2] = await this.#startTask(exitReason.agentName, exitReason.task, context2, remainIteration, callback);
|
|
34408
34675
|
info2.inputTokens += info.inputTokens;
|
|
34409
34676
|
info2.outputTokens += info.outputTokens;
|
|
34410
34677
|
info2.cacheWriteTokens += info.cacheWriteTokens;
|
|
@@ -34418,7 +34685,8 @@ class MultiAgent {
|
|
|
34418
34685
|
if (this.#activeAgent) {
|
|
34419
34686
|
throw new Error("An active agent already exists");
|
|
34420
34687
|
}
|
|
34421
|
-
|
|
34688
|
+
const maxIterations = options.maxIterations ?? 50;
|
|
34689
|
+
return this.#startTask(options.agentName, options.task, options.context, maxIterations, options.callback);
|
|
34422
34690
|
}
|
|
34423
34691
|
async continueTask(userMessage, taskInfo, callback = () => {
|
|
34424
34692
|
}) {
|
|
@@ -34490,6 +34758,8 @@ ${output}`);
|
|
|
34490
34758
|
|
|
34491
34759
|
// ../core/src/AiTool/generateGithubPullRequestDetails.ts
|
|
34492
34760
|
var prompt2 = `
|
|
34761
|
+
# Generate Github Pull Request Details
|
|
34762
|
+
|
|
34493
34763
|
You are given:
|
|
34494
34764
|
- A branch name in <tool_input_branch_name>.
|
|
34495
34765
|
- An optional context message in <tool_input_context> (which may or may not be present).
|
|
@@ -34502,10 +34772,30 @@ Your task:
|
|
|
34502
34772
|
3. Produce a single GitHub Pull Request title.
|
|
34503
34773
|
4. Produce a Pull Request description that explains the changes.
|
|
34504
34774
|
|
|
34775
|
+
Use the following template for the Pull Request description:
|
|
34776
|
+
|
|
34777
|
+
---
|
|
34778
|
+
**Context (if provided)**:
|
|
34779
|
+
- Acknowledge any guiding concerns or instructions.
|
|
34780
|
+
|
|
34781
|
+
**Summary of Changes**:
|
|
34782
|
+
- Provide a concise list or overview of what changed.
|
|
34783
|
+
|
|
34784
|
+
**Highlights of Changed Code**:
|
|
34785
|
+
- Mention only the specific sections or functionalities updated, without showing full surrounding context.
|
|
34786
|
+
|
|
34787
|
+
**Additional Information (if needed)**:
|
|
34788
|
+
- Testing steps (if applicable).
|
|
34789
|
+
- Any notes or caveats.
|
|
34790
|
+
|
|
34791
|
+
---
|
|
34792
|
+
|
|
34505
34793
|
Output format:
|
|
34506
34794
|
<tool_output>
|
|
34507
34795
|
<tool_output_pr_title>YOUR PR TITLE HERE</tool_output_pr_title>
|
|
34508
|
-
<tool_output_pr_description>
|
|
34796
|
+
<tool_output_pr_description>
|
|
34797
|
+
YOUR PR DESCRIPTION HERE
|
|
34798
|
+
</tool_output_pr_description>
|
|
34509
34799
|
</tool_output>
|
|
34510
34800
|
|
|
34511
34801
|
Below is an **example** of the input and output:
|
|
@@ -34527,7 +34817,7 @@ diff --git a/order_service.py b/order_service.py
|
|
|
34527
34817
|
- if is_valid_order(order):
|
|
34528
34818
|
- process_order(order)
|
|
34529
34819
|
+ validate_and_process(order)
|
|
34530
|
-
|
|
34820
|
+
</tool_input_commit_diff>
|
|
34531
34821
|
</tool_input>
|
|
34532
34822
|
|
|
34533
34823
|
Example Output:
|
|
@@ -34541,8 +34831,7 @@ to use the new validate_and_process method for improved maintainability.
|
|
|
34541
34831
|
|
|
34542
34832
|
---
|
|
34543
34833
|
|
|
34544
|
-
Use the above format whenever you receive
|
|
34545
|
-
Only highlight the changed code and avoid including the context around the changes in the description.
|
|
34834
|
+
Use the above format whenever you receive <tool_input> that may include a branch name, an optional context, aggregated commit messages in a single tag, and a combined diff in a single tag. Provide your final output strictly in <tool_output> with <tool_output_pr_title> and <tool_output_pr_description>. Only highlight the changed code and avoid including the context around the changes in the description.
|
|
34546
34835
|
`;
|
|
34547
34836
|
var generateGithubPullRequestDetails_default = {
|
|
34548
34837
|
name: "generateGithubPullRequestDetails",
|
|
@@ -34730,7 +35019,7 @@ import os from "node:os";
|
|
|
34730
35019
|
// src/provider.ts
|
|
34731
35020
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
34732
35021
|
import { spawn as spawn2 } from "node:child_process";
|
|
34733
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
35022
|
+
import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
34734
35023
|
import { dirname } from "node:path";
|
|
34735
35024
|
|
|
34736
35025
|
// src/utils/listFiles.ts
|
|
@@ -34843,7 +35132,7 @@ async function searchFiles(path2, regex, filePattern, cwd, excludeFiles) {
|
|
|
34843
35132
|
rg.stderr.on("data", (data) => {
|
|
34844
35133
|
const err = data.toString();
|
|
34845
35134
|
if (!err.startsWith("WARNING:")) {
|
|
34846
|
-
console.
|
|
35135
|
+
console.warn(err);
|
|
34847
35136
|
}
|
|
34848
35137
|
});
|
|
34849
35138
|
rg.on("error", (error) => {
|
|
@@ -34876,6 +35165,18 @@ var getProvider = (options) => {
|
|
|
34876
35165
|
await mkdir(dirname(path2), { recursive: true });
|
|
34877
35166
|
return await writeFile(path2, content, "utf8");
|
|
34878
35167
|
},
|
|
35168
|
+
removeFile: async (path2) => {
|
|
35169
|
+
if (ig.ignores(path2)) {
|
|
35170
|
+
throw new Error(`Not allow to access file ${path2}`);
|
|
35171
|
+
}
|
|
35172
|
+
return await unlink(path2);
|
|
35173
|
+
},
|
|
35174
|
+
renameFile: async (sourcePath, targetPath) => {
|
|
35175
|
+
if (ig.ignores(sourcePath) || ig.ignores(targetPath)) {
|
|
35176
|
+
throw new Error(`Not allow to access file ${sourcePath} or ${targetPath}`);
|
|
35177
|
+
}
|
|
35178
|
+
return await rename(sourcePath, targetPath);
|
|
35179
|
+
},
|
|
34879
35180
|
listFiles: async (path2, recursive, maxCount) => {
|
|
34880
35181
|
return await listFiles(path2, recursive, maxCount, dirname(path2), options.excludeFiles);
|
|
34881
35182
|
},
|
|
@@ -39229,7 +39530,7 @@ var readConfig = (path2) => {
|
|
|
39229
39530
|
|
|
39230
39531
|
// src/options.ts
|
|
39231
39532
|
function addSharedOptions(command) {
|
|
39232
|
-
return command.option("-c --config <path>", "Path to config file").option("--api-provider <provider>", "API provider").option("--model <model>", "Model ID").option("--api-key <key>", "API key").option("--max-iterations <iterations>", "Maximum number of iterations to run. Default to 30", Number.parseInt);
|
|
39533
|
+
return command.option("-c --config <path>", "Path to config file").option("--api-provider <provider>", "API provider").option("--model <model>", "Model ID").option("--api-key <key>", "API key").option("--max-iterations <iterations>", "Maximum number of iterations to run. Default to 30", Number.parseInt).option("-v --verbose", "Enable verbose output. Use -v for level 1, -vv for level 2", (value, prev) => prev + 1, 0);
|
|
39233
39534
|
}
|
|
39234
39535
|
|
|
39235
39536
|
class ApiProviderConfig {
|
|
@@ -39298,6 +39599,7 @@ function parseOptions(options, cwd = process.cwd(), home = os2.homedir()) {
|
|
|
39298
39599
|
});
|
|
39299
39600
|
return {
|
|
39300
39601
|
maxIterations: options.maxIterations ?? 30,
|
|
39602
|
+
verbose: options.verbose ?? 0,
|
|
39301
39603
|
config,
|
|
39302
39604
|
providerConfig
|
|
39303
39605
|
};
|
|
@@ -39788,13 +40090,32 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
39788
40090
|
var source_default = chalk;
|
|
39789
40091
|
|
|
39790
40092
|
// src/utils/eventHandler.ts
|
|
39791
|
-
var printEvent = (event) => {
|
|
40093
|
+
var printEvent = (verbose) => (event) => {
|
|
40094
|
+
let hadReasoning = false;
|
|
39792
40095
|
switch (event.kind) {
|
|
40096
|
+
case "StartTask" /* StartTask */:
|
|
40097
|
+
if (verbose > 1) {
|
|
40098
|
+
console.log(`
|
|
40099
|
+
====== System Prompt ======
|
|
40100
|
+
${event.systemPrompt}`);
|
|
40101
|
+
console.log(`
|
|
40102
|
+
|
|
40103
|
+
================
|
|
40104
|
+
`);
|
|
40105
|
+
}
|
|
40106
|
+
break;
|
|
39793
40107
|
case "StartRequest" /* StartRequest */:
|
|
39794
40108
|
console.log(`
|
|
39795
40109
|
|
|
39796
40110
|
======== New Request ========
|
|
39797
40111
|
`);
|
|
40112
|
+
if (verbose) {
|
|
40113
|
+
console.log(event.userMessage);
|
|
40114
|
+
console.log(`
|
|
40115
|
+
|
|
40116
|
+
======== Request Message Ended ========
|
|
40117
|
+
`);
|
|
40118
|
+
}
|
|
39798
40119
|
break;
|
|
39799
40120
|
case "EndRequest" /* EndRequest */:
|
|
39800
40121
|
console.log(`
|
|
@@ -39805,10 +40126,17 @@ var printEvent = (event) => {
|
|
|
39805
40126
|
case "Usage" /* Usage */:
|
|
39806
40127
|
break;
|
|
39807
40128
|
case "Text" /* Text */:
|
|
40129
|
+
if (hadReasoning) {
|
|
40130
|
+
process.stdout.write(`
|
|
40131
|
+
|
|
40132
|
+
`);
|
|
40133
|
+
hadReasoning = false;
|
|
40134
|
+
}
|
|
39808
40135
|
process.stdout.write(event.newText);
|
|
39809
40136
|
break;
|
|
39810
40137
|
case "Reasoning" /* Reasoning */:
|
|
39811
40138
|
process.stdout.write(source_default.dim(event.newText));
|
|
40139
|
+
hadReasoning = true;
|
|
39812
40140
|
break;
|
|
39813
40141
|
case "ToolUse" /* ToolUse */:
|
|
39814
40142
|
break;
|
|
@@ -40404,15 +40732,15 @@ function useKeypress(userHandler) {
|
|
|
40404
40732
|
signal.current = userHandler;
|
|
40405
40733
|
useEffect((rl) => {
|
|
40406
40734
|
let ignore3 = false;
|
|
40407
|
-
const
|
|
40735
|
+
const handler13 = withUpdates((_input, event) => {
|
|
40408
40736
|
if (ignore3)
|
|
40409
40737
|
return;
|
|
40410
40738
|
signal.current(event, rl);
|
|
40411
40739
|
});
|
|
40412
|
-
rl.input.on("keypress",
|
|
40740
|
+
rl.input.on("keypress", handler13);
|
|
40413
40741
|
return () => {
|
|
40414
40742
|
ignore3 = true;
|
|
40415
|
-
rl.input.removeListener("keypress",
|
|
40743
|
+
rl.input.removeListener("keypress", handler13);
|
|
40416
40744
|
};
|
|
40417
40745
|
}, []);
|
|
40418
40746
|
}
|
|
@@ -40594,16 +40922,16 @@ class Emitter {
|
|
|
40594
40922
|
|
|
40595
40923
|
class SignalExitBase {
|
|
40596
40924
|
}
|
|
40597
|
-
var signalExitWrap = (
|
|
40925
|
+
var signalExitWrap = (handler13) => {
|
|
40598
40926
|
return {
|
|
40599
40927
|
onExit(cb, opts) {
|
|
40600
|
-
return
|
|
40928
|
+
return handler13.onExit(cb, opts);
|
|
40601
40929
|
},
|
|
40602
40930
|
load() {
|
|
40603
|
-
return
|
|
40931
|
+
return handler13.load();
|
|
40604
40932
|
},
|
|
40605
40933
|
unload() {
|
|
40606
|
-
return
|
|
40934
|
+
return handler13.unload();
|
|
40607
40935
|
}
|
|
40608
40936
|
};
|
|
40609
40937
|
};
|
|
@@ -41257,6 +41585,9 @@ async function configPrompt(existingConfig) {
|
|
|
41257
41585
|
case "deepseek" /* DeepSeek */:
|
|
41258
41586
|
model = deepSeekDefaultModelId;
|
|
41259
41587
|
break;
|
|
41588
|
+
case "openrouter" /* OpenRouter */:
|
|
41589
|
+
model = await esm_default3({ message: "Enter Model ID (Visit https://openrouter.ai/models for available models):" });
|
|
41590
|
+
break;
|
|
41260
41591
|
}
|
|
41261
41592
|
let apiKey;
|
|
41262
41593
|
if (provider2 !== "ollama" /* Ollama */) {
|
|
@@ -41280,7 +41611,7 @@ async function printConfig(configPath) {
|
|
|
41280
41611
|
}
|
|
41281
41612
|
console.log($stringify(config));
|
|
41282
41613
|
}
|
|
41283
|
-
|
|
41614
|
+
var configCommand = new Command("config").description("Configure global or local settings").option("-g, --global", "Use global config").option("-p, --print", "Print config").action(async (options) => {
|
|
41284
41615
|
const globalConfigPath = getGlobalConfigPath();
|
|
41285
41616
|
let configPath = options.global ? globalConfigPath : localConfigFileName;
|
|
41286
41617
|
if (options.print) {
|
|
@@ -41367,12 +41698,11 @@ ${provider2.toUpperCase()}_API_KEY=${apiKey}`;
|
|
|
41367
41698
|
mkdirSync(dirname2(configPath), { recursive: true });
|
|
41368
41699
|
writeFileSync(configPath, $stringify(newConfig));
|
|
41369
41700
|
console.log(`Config file saved at: ${configPath}`);
|
|
41370
|
-
|
|
41371
|
-
}
|
|
41701
|
+
});
|
|
41372
41702
|
|
|
41373
41703
|
// src/commands/chat.ts
|
|
41374
41704
|
var runChat = async (options) => {
|
|
41375
|
-
const { config, providerConfig, maxIterations } = parseOptions(options);
|
|
41705
|
+
const { config, providerConfig, maxIterations, verbose } = parseOptions(options);
|
|
41376
41706
|
let { provider: provider2, model, apiKey } = providerConfig.getConfigForAgent("coder") ?? {};
|
|
41377
41707
|
if (!provider2) {
|
|
41378
41708
|
const newConfig = await configPrompt({ provider: provider2, model, apiKey });
|
|
@@ -41392,7 +41722,7 @@ var runChat = async (options) => {
|
|
|
41392
41722
|
config: config ?? {},
|
|
41393
41723
|
maxIterations,
|
|
41394
41724
|
interactive: true,
|
|
41395
|
-
eventCallback: printEvent
|
|
41725
|
+
eventCallback: printEvent(verbose)
|
|
41396
41726
|
});
|
|
41397
41727
|
let taskInfo;
|
|
41398
41728
|
const chat2 = new Chat3({
|
|
@@ -42161,12 +42491,57 @@ var prCommand = new Command("pr").description("Create a GitHub pull request").ar
|
|
|
42161
42491
|
});
|
|
42162
42492
|
|
|
42163
42493
|
// src/commands/task.ts
|
|
42494
|
+
var readStdin = async (timeoutMs = 30000) => {
|
|
42495
|
+
if (process.stdin.isTTY) {
|
|
42496
|
+
return "";
|
|
42497
|
+
}
|
|
42498
|
+
return new Promise((resolve2, reject) => {
|
|
42499
|
+
let input = "";
|
|
42500
|
+
let timeoutId = undefined;
|
|
42501
|
+
const cleanup = () => {
|
|
42502
|
+
if (timeoutId)
|
|
42503
|
+
clearTimeout(timeoutId);
|
|
42504
|
+
process.stdin.removeAllListeners();
|
|
42505
|
+
process.stdin.resume();
|
|
42506
|
+
};
|
|
42507
|
+
timeoutId = setTimeout(() => {
|
|
42508
|
+
cleanup();
|
|
42509
|
+
reject(new Error("Stdin read timeout"));
|
|
42510
|
+
}, timeoutMs);
|
|
42511
|
+
process.stdin.on("data", (chunk) => {
|
|
42512
|
+
input += chunk.toString();
|
|
42513
|
+
});
|
|
42514
|
+
process.stdin.on("end", () => {
|
|
42515
|
+
cleanup();
|
|
42516
|
+
if (!input) {
|
|
42517
|
+
reject(new Error("Empty stdin input"));
|
|
42518
|
+
return;
|
|
42519
|
+
}
|
|
42520
|
+
resolve2(input);
|
|
42521
|
+
});
|
|
42522
|
+
process.stdin.on("error", (err) => {
|
|
42523
|
+
cleanup();
|
|
42524
|
+
reject(err);
|
|
42525
|
+
});
|
|
42526
|
+
});
|
|
42527
|
+
};
|
|
42164
42528
|
var runTask = async (taskArg, options) => {
|
|
42165
|
-
|
|
42166
|
-
|
|
42167
|
-
|
|
42529
|
+
let task = taskArg;
|
|
42530
|
+
if (!task) {
|
|
42531
|
+
try {
|
|
42532
|
+
const stdinInput = await readStdin();
|
|
42533
|
+
if (stdinInput) {
|
|
42534
|
+
task = stdinInput;
|
|
42535
|
+
} else {
|
|
42536
|
+
runChat(options);
|
|
42537
|
+
return;
|
|
42538
|
+
}
|
|
42539
|
+
} catch (error) {
|
|
42540
|
+
console.error("Error reading stdin:", error);
|
|
42541
|
+
process.exit(1);
|
|
42542
|
+
}
|
|
42168
42543
|
}
|
|
42169
|
-
const { providerConfig, config, maxIterations } = parseOptions(options);
|
|
42544
|
+
const { providerConfig, config, maxIterations, verbose } = parseOptions(options);
|
|
42170
42545
|
let { provider: provider2, model, apiKey } = providerConfig.getConfigForAgent("coder") ?? {};
|
|
42171
42546
|
if (!provider2) {
|
|
42172
42547
|
const newConfig = await configPrompt({ provider: provider2, model, apiKey });
|
|
@@ -42183,18 +42558,18 @@ var runTask = async (taskArg, options) => {
|
|
|
42183
42558
|
config: config ?? {},
|
|
42184
42559
|
maxIterations,
|
|
42185
42560
|
interactive: false,
|
|
42186
|
-
eventCallback: printEvent
|
|
42561
|
+
eventCallback: printEvent(verbose)
|
|
42187
42562
|
});
|
|
42188
|
-
await runner.startTask(
|
|
42563
|
+
await runner.startTask(task);
|
|
42189
42564
|
runner.printUsage();
|
|
42190
42565
|
};
|
|
42191
42566
|
|
|
42192
42567
|
// src/index.ts
|
|
42193
42568
|
var program2 = new Command;
|
|
42194
|
-
program2.name("polka").description("Polka Codes CLI").version(version);
|
|
42195
|
-
program2.command("chat").description("Start an interactive chat session").action(runChat);
|
|
42196
|
-
program2.command("config").description("Configure global or local settings").option("-g, --global", "Use global config").option("-p, --print", "Print config").action(configCommand);
|
|
42569
|
+
program2.name("polka-codes").description("Polka Codes CLI").version(version);
|
|
42197
42570
|
program2.argument("[task]", "The task to execute").action(runTask);
|
|
42571
|
+
program2.command("chat").description("Start an interactive chat session").action(runChat);
|
|
42572
|
+
program2.addCommand(configCommand);
|
|
42198
42573
|
program2.addCommand(commitCommand);
|
|
42199
42574
|
program2.addCommand(prCommand);
|
|
42200
42575
|
addSharedOptions(program2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polka-codes/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@inquirer/prompts": "^7.2.3",
|
|
20
|
-
"@polka-codes/core": "0.4.
|
|
20
|
+
"@polka-codes/core": "0.4.5",
|
|
21
21
|
"@vscode/ripgrep": "^1.15.10",
|
|
22
22
|
"chalk": "^5.4.1",
|
|
23
23
|
"commander": "^13.0.0",
|