@polka-codes/core 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +997 -558
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7933,7 +7933,7 @@ class OllamaService extends AiServiceBase {
|
|
|
7933
7933
|
apiKey: "ollama"
|
|
7934
7934
|
});
|
|
7935
7935
|
this.model = {
|
|
7936
|
-
id: options.modelId || "",
|
|
7936
|
+
id: options.modelId || "maryasov/qwen2.5-coder-cline:7b",
|
|
7937
7937
|
info: openAiModelInfoSaneDefaults
|
|
7938
7938
|
};
|
|
7939
7939
|
}
|
|
@@ -7970,6 +7970,11 @@ var AiServiceProvider;
|
|
|
7970
7970
|
AiServiceProvider2["Ollama"] = "ollama";
|
|
7971
7971
|
AiServiceProvider2["DeepSeek"] = "deepseek";
|
|
7972
7972
|
})(AiServiceProvider ||= {});
|
|
7973
|
+
var defaultModels = {
|
|
7974
|
+
["anthropic" /* Anthropic */]: "claude-3-5-sonnet-20241022",
|
|
7975
|
+
["ollama" /* Ollama */]: "maryasov/qwen2.5-coder-cline:7b",
|
|
7976
|
+
["deepseek" /* DeepSeek */]: "deepseek-chat"
|
|
7977
|
+
};
|
|
7973
7978
|
var createService = (provider, options) => {
|
|
7974
7979
|
switch (provider) {
|
|
7975
7980
|
case "anthropic" /* Anthropic */:
|
|
@@ -7980,265 +7985,704 @@ var createService = (provider, options) => {
|
|
|
7980
7985
|
return new DeepSeekService(options);
|
|
7981
7986
|
}
|
|
7982
7987
|
};
|
|
7983
|
-
// src/
|
|
7984
|
-
var
|
|
7985
|
-
((
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
}
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
|
|
8014
|
-
|
|
8015
|
-
|
|
8016
|
-
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
7988
|
+
// src/tool.ts
|
|
7989
|
+
var getAvailableTools = (provider, allTools) => {
|
|
7990
|
+
return allTools.filter((tool) => tool.isAvailable(provider));
|
|
7991
|
+
};
|
|
7992
|
+
|
|
7993
|
+
// src/Agent/parseAssistantMessage.ts
|
|
7994
|
+
function parseAssistantMessage(assistantMessage, tools, toolNamePrefix) {
|
|
7995
|
+
const parameterPrefix = `${toolNamePrefix}parameter_`;
|
|
7996
|
+
const results = [];
|
|
7997
|
+
const toolTags = tools.map((tool) => `${toolNamePrefix}${tool.name}`);
|
|
7998
|
+
const toolPattern = toolTags.join("|");
|
|
7999
|
+
const tagRegex = new RegExp(`<(${toolPattern})>(.*)<\\/\\1>`, "s");
|
|
8000
|
+
const match = assistantMessage.match(tagRegex);
|
|
8001
|
+
if (match) {
|
|
8002
|
+
const beforeTag = assistantMessage.slice(0, match.index).trim();
|
|
8003
|
+
const fullTagContent = match[0];
|
|
8004
|
+
if (beforeTag) {
|
|
8005
|
+
results.push({
|
|
8006
|
+
type: "text",
|
|
8007
|
+
content: beforeTag
|
|
8008
|
+
});
|
|
8009
|
+
}
|
|
8010
|
+
const tagName = match[1];
|
|
8011
|
+
const toolName = tagName.replace(toolNamePrefix, "");
|
|
8012
|
+
const tool = tools.find((t) => t.name === toolName);
|
|
8013
|
+
if (tool) {
|
|
8014
|
+
const params = {};
|
|
8015
|
+
for (const param of tool.parameters) {
|
|
8016
|
+
const paramName = `${parameterPrefix}${param.name}`;
|
|
8017
|
+
const escapedParamName = paramName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8018
|
+
const paramPattern = `<${escapedParamName}>([\\s\\S]*?)<\\/${escapedParamName}>`;
|
|
8019
|
+
const paramMatch = fullTagContent.match(new RegExp(paramPattern, "s"));
|
|
8020
|
+
if (paramMatch) {
|
|
8021
|
+
params[param.name] = paramMatch[1].trim();
|
|
8022
|
+
}
|
|
8023
|
+
}
|
|
8024
|
+
results.push({
|
|
8025
|
+
type: "tool_use",
|
|
8026
|
+
name: toolName,
|
|
8027
|
+
params
|
|
8028
|
+
});
|
|
8029
|
+
} else {
|
|
8030
|
+
results.push({
|
|
8031
|
+
type: "text",
|
|
8032
|
+
content: fullTagContent
|
|
8033
|
+
});
|
|
8034
|
+
}
|
|
8035
|
+
const afterTag = assistantMessage.slice((match.index ?? 0) + fullTagContent.length).trim();
|
|
8036
|
+
if (afterTag) {
|
|
8037
|
+
results.push({
|
|
8038
|
+
type: "text",
|
|
8039
|
+
content: afterTag
|
|
8040
|
+
});
|
|
8041
|
+
}
|
|
8042
|
+
} else {
|
|
8043
|
+
results.push({
|
|
8044
|
+
type: "text",
|
|
8045
|
+
content: assistantMessage
|
|
8046
|
+
});
|
|
8047
|
+
}
|
|
8048
|
+
return results;
|
|
8049
|
+
}
|
|
8050
|
+
|
|
8051
|
+
// src/Agent/prompts.ts
|
|
8052
|
+
var toolInfoPrompt = (tool, toolNamePrefix, parameterPrefix) => `
|
|
8053
|
+
## ${toolNamePrefix}${tool.name}
|
|
8054
|
+
|
|
8055
|
+
Description: ${tool.description}
|
|
8056
|
+
|
|
8057
|
+
Parameters:
|
|
8058
|
+
${tool.parameters.map((param) => `- ${parameterPrefix}${param.name}: (${param.required ? "required" : "optional"}) ${param.description}`).join(`
|
|
8059
|
+
`)}
|
|
8060
|
+
|
|
8061
|
+
Usage:
|
|
8062
|
+
<${toolNamePrefix}${tool.name}>
|
|
8063
|
+
${tool.parameters.map((param) => `<${parameterPrefix}${param.name}>${param.usageValue}</${parameterPrefix}${param.name}>`).join(`
|
|
8064
|
+
`)}
|
|
8065
|
+
</${toolNamePrefix}${tool.name}>`;
|
|
8066
|
+
var toolInfoExamplesPrompt = (idx, tool, example, toolNamePrefix, parameterPrefix) => `
|
|
8067
|
+
## Example ${idx + 1}: ${example.description}
|
|
8068
|
+
|
|
8069
|
+
<${toolNamePrefix}${tool.name}>
|
|
8070
|
+
${example.parameters.map((param) => `<${parameterPrefix}${param.name}>${param.value}</${parameterPrefix}${param.name}>`).join(`
|
|
8071
|
+
`)}
|
|
8072
|
+
</${toolNamePrefix}${tool.name}>
|
|
8073
|
+
`;
|
|
8074
|
+
var toolUsePrompt = (tools, toolNamePrefix) => {
|
|
8075
|
+
if (tools.length === 0) {
|
|
8076
|
+
return "";
|
|
8077
|
+
}
|
|
8078
|
+
const parameterPrefix = `${toolNamePrefix}parameter_`;
|
|
8079
|
+
let exampleIndex = 0;
|
|
8080
|
+
return `
|
|
8081
|
+
====
|
|
8082
|
+
|
|
8083
|
+
TOOL USE
|
|
8084
|
+
|
|
8085
|
+
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
|
8086
|
+
|
|
8087
|
+
# Tool Use Formatting
|
|
8088
|
+
|
|
8089
|
+
Tool use is formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:
|
|
8090
|
+
|
|
8091
|
+
<${toolNamePrefix}tool_name>
|
|
8092
|
+
<${parameterPrefix}name1>value1</${parameterPrefix}name1>
|
|
8093
|
+
<${parameterPrefix}name2>value2</${parameterPrefix}name2>
|
|
8094
|
+
...
|
|
8095
|
+
</${toolNamePrefix}tool_name>
|
|
8096
|
+
|
|
8097
|
+
For example:
|
|
8098
|
+
|
|
8099
|
+
<${toolNamePrefix}read_file>
|
|
8100
|
+
<${parameterPrefix}path>src/main.js</${parameterPrefix}path>
|
|
8101
|
+
</${toolNamePrefix}read_file>
|
|
8102
|
+
|
|
8103
|
+
Always adhere to this format for the tool use to ensure proper parsing and execution.
|
|
8104
|
+
|
|
8105
|
+
# Tools
|
|
8106
|
+
${tools.map((tool) => toolInfoPrompt(tool, toolNamePrefix, parameterPrefix)).join(`
|
|
8107
|
+
`)}
|
|
8108
|
+
|
|
8109
|
+
# Tool Use Examples
|
|
8110
|
+
${tools.map((tool) => {
|
|
8111
|
+
let promp = "";
|
|
8112
|
+
for (const example of tool.examples ?? []) {
|
|
8113
|
+
promp += toolInfoExamplesPrompt(exampleIndex++, tool, example, toolNamePrefix, parameterPrefix);
|
|
8114
|
+
}
|
|
8115
|
+
return promp;
|
|
8116
|
+
}).join("")}
|
|
8117
|
+
# Tool Use Guidelines
|
|
8118
|
+
|
|
8119
|
+
1. **In \`<thinking>\` tags**, assess what information you have and what you need to proceed.
|
|
8120
|
+
2. **Choose one tool at a time per message** based on the task and its description. Do not assume a tool’s outcome without explicit confirmation.
|
|
8121
|
+
3. **Formulate tool use only in the specified XML format** for each tool.
|
|
8122
|
+
4. **Wait for the user’s response** after each tool use. Do not proceed until you have their confirmation.
|
|
8123
|
+
5. The user’s response may include:
|
|
8124
|
+
- Tool success or failure details
|
|
8125
|
+
- Linter errors
|
|
8126
|
+
- Terminal output or other relevant feedback
|
|
8127
|
+
6. **Never repeat or quote the entire tool command** in your final user-facing message. Summarize outcomes clearly and avoid echoing commands verbatim.
|
|
8128
|
+
7. **Respond concisely** and move the conversation forward. Do not re-issue the same command or re-trigger tool use without necessity.
|
|
8129
|
+
8. Follow these steps **iteratively**, confirming success and addressing issues as you go.
|
|
8130
|
+
|
|
8131
|
+
By adhering to these guidelines:
|
|
8132
|
+
- You maintain clarity without accidentally re-invoking tools.
|
|
8133
|
+
- You confirm each step’s results before proceeding.
|
|
8134
|
+
- You provide only the necessary information in user-facing replies to prevent re-interpretation as new commands.`;
|
|
8135
|
+
};
|
|
8136
|
+
var responsePrompts = {
|
|
8137
|
+
errorInvokeTool: (tool, error) => `An error occurred while invoking the tool "${tool}": ${error}`,
|
|
8138
|
+
requireUseTool: "Error: You must use a tool before proceeding",
|
|
8139
|
+
toolResults: (tool, result) => `<tool_response>
|
|
8140
|
+
<tool_name>${tool}</tool_name>
|
|
8141
|
+
<tool_result>
|
|
8142
|
+
${result}
|
|
8143
|
+
</tool_result>
|
|
8144
|
+
</tool_response>`
|
|
8145
|
+
};
|
|
8146
|
+
|
|
8147
|
+
// src/Agent/AgentBase.ts
|
|
8148
|
+
var ExitReason;
|
|
8149
|
+
((ExitReason2) => {
|
|
8150
|
+
ExitReason2["Completed"] = "Completed";
|
|
8151
|
+
ExitReason2["MaxIterations"] = "MaxIterations";
|
|
8152
|
+
ExitReason2["WaitForUserInput"] = "WaitForUserInput";
|
|
8153
|
+
ExitReason2["Interrupted"] = "Interrupted";
|
|
8154
|
+
})(ExitReason ||= {});
|
|
8155
|
+
|
|
8156
|
+
class AgentBase {
|
|
8157
|
+
ai;
|
|
8158
|
+
config;
|
|
8159
|
+
logger;
|
|
8160
|
+
handlers;
|
|
8161
|
+
constructor(ai, config, logger6) {
|
|
8162
|
+
this.ai = ai;
|
|
8163
|
+
this.config = config;
|
|
8164
|
+
this.logger = logger6;
|
|
8165
|
+
const handlers = {};
|
|
8166
|
+
for (const tool of config.tools) {
|
|
8167
|
+
handlers[tool.name] = tool;
|
|
8168
|
+
}
|
|
8169
|
+
this.handlers = handlers;
|
|
8170
|
+
}
|
|
8171
|
+
async startTask({
|
|
8172
|
+
task,
|
|
8173
|
+
context,
|
|
8174
|
+
maxIterations = 50,
|
|
8175
|
+
callback = () => {
|
|
8176
|
+
}
|
|
8177
|
+
}) {
|
|
8178
|
+
const taskInfo = {
|
|
8179
|
+
options: {
|
|
8180
|
+
maxIterations
|
|
8181
|
+
},
|
|
8182
|
+
messages: [],
|
|
8183
|
+
inputTokens: 0,
|
|
8184
|
+
outputTokens: 0,
|
|
8185
|
+
cacheWriteTokens: 0,
|
|
8186
|
+
cacheReadTokens: 0,
|
|
8187
|
+
totalCost: 0
|
|
8188
|
+
};
|
|
8189
|
+
let text = `<task>${task}</task>`;
|
|
8190
|
+
if (context) {
|
|
8191
|
+
text += `
|
|
8192
|
+
<context>${context}</context>`;
|
|
8193
|
+
}
|
|
8194
|
+
return await this.#processLoop(text, taskInfo, callback);
|
|
8195
|
+
}
|
|
8196
|
+
async#processLoop(userMessage, taskInfo, callback) {
|
|
8197
|
+
let nextRequest = userMessage;
|
|
8198
|
+
while (nextRequest) {
|
|
8199
|
+
if (taskInfo.messages.length > taskInfo.options.maxIterations * 2) {
|
|
8200
|
+
callback({ kind: "max_iterations_reached", info: taskInfo });
|
|
8201
|
+
return ["MaxIterations" /* MaxIterations */, taskInfo];
|
|
8202
|
+
}
|
|
8203
|
+
const response = await this.#request(taskInfo, nextRequest, callback);
|
|
8204
|
+
const [newMessage, exitReason] = await this.#handleResponse(taskInfo, response, callback);
|
|
8205
|
+
if (exitReason) {
|
|
8206
|
+
return [exitReason, taskInfo];
|
|
8207
|
+
}
|
|
8208
|
+
nextRequest = newMessage;
|
|
8209
|
+
}
|
|
8210
|
+
callback({ kind: "end_task", info: taskInfo });
|
|
8211
|
+
return ["Completed" /* Completed */, taskInfo];
|
|
8212
|
+
}
|
|
8213
|
+
async continueTask(userMessage, taskInfo, callback) {
|
|
8214
|
+
return await this.#processLoop(userMessage, taskInfo, callback);
|
|
8215
|
+
}
|
|
8216
|
+
async#request(info, userMessage, callback) {
|
|
8217
|
+
await callback({ kind: "start_request", info, userMessage });
|
|
8218
|
+
info.messages.push({
|
|
8219
|
+
role: "user",
|
|
8220
|
+
content: userMessage
|
|
8221
|
+
});
|
|
8222
|
+
this.logger.trace(info.messages, "Sending messages to AI");
|
|
8223
|
+
const stream = this.ai.send(this.config.systemPrompt, info.messages);
|
|
8224
|
+
let currentAssistantMessage = "";
|
|
8225
|
+
for await (const chunk of stream) {
|
|
8226
|
+
switch (chunk.type) {
|
|
8227
|
+
case "usage":
|
|
8228
|
+
info.inputTokens = chunk.inputTokens;
|
|
8229
|
+
info.outputTokens = chunk.outputTokens;
|
|
8230
|
+
info.cacheWriteTokens = chunk.cacheWriteTokens ?? 0;
|
|
8231
|
+
info.cacheReadTokens = chunk.cacheReadTokens ?? 0;
|
|
8232
|
+
info.totalCost = chunk.totalCost;
|
|
8233
|
+
await callback({ kind: "usage", info });
|
|
8234
|
+
break;
|
|
8235
|
+
case "text":
|
|
8236
|
+
currentAssistantMessage += chunk.text;
|
|
8237
|
+
await callback({ kind: "text", info, newText: chunk.text });
|
|
8238
|
+
break;
|
|
8239
|
+
}
|
|
8240
|
+
}
|
|
8241
|
+
if (!currentAssistantMessage) {
|
|
8242
|
+
throw new Error("No assistant message received");
|
|
8243
|
+
}
|
|
8244
|
+
info.messages.push({
|
|
8245
|
+
role: "assistant",
|
|
8246
|
+
content: currentAssistantMessage
|
|
8247
|
+
});
|
|
8248
|
+
const ret = parseAssistantMessage(currentAssistantMessage, this.config.tools, this.config.toolNamePrefix);
|
|
8249
|
+
await callback({ kind: "end_request", info });
|
|
8250
|
+
return ret;
|
|
8251
|
+
}
|
|
8252
|
+
async#handleResponse(info, response, callback) {
|
|
8253
|
+
const toolReponses = [];
|
|
8254
|
+
for (const content of response) {
|
|
8255
|
+
switch (content.type) {
|
|
8256
|
+
case "text":
|
|
8257
|
+
break;
|
|
8258
|
+
case "tool_use": {
|
|
8259
|
+
await callback({ kind: "tool_use", info, tool: content.name });
|
|
8260
|
+
const toolResp = await this.#invokeTool(content.name, content.params);
|
|
8261
|
+
switch (toolResp.type) {
|
|
8262
|
+
case "Reply" /* Reply */:
|
|
8263
|
+
await callback({ kind: "tool_reply", info, tool: content.name });
|
|
8264
|
+
toolReponses.push({ tool: content.name, response: toolResp.message });
|
|
8265
|
+
break;
|
|
8266
|
+
case "Exit" /* Exit */:
|
|
8267
|
+
return [undefined, "Completed" /* Completed */];
|
|
8268
|
+
case "Invalid" /* Invalid */:
|
|
8269
|
+
await callback({ kind: "tool_invalid", info, tool: content.name });
|
|
8270
|
+
toolReponses.push({ tool: content.name, response: toolResp.message });
|
|
8271
|
+
break;
|
|
8272
|
+
case "Error" /* Error */:
|
|
8273
|
+
await callback({ kind: "tool_error", info, tool: content.name });
|
|
8274
|
+
toolReponses.push({ tool: content.name, response: toolResp.message });
|
|
8275
|
+
break;
|
|
8276
|
+
case "Interrupted" /* Interrupted */:
|
|
8277
|
+
await callback({ kind: "tool_interrupted", info, tool: content.name });
|
|
8278
|
+
return [undefined, "Interrupted" /* Interrupted */];
|
|
8279
|
+
}
|
|
8280
|
+
break;
|
|
8281
|
+
}
|
|
8282
|
+
}
|
|
8283
|
+
}
|
|
8284
|
+
if (toolReponses.length === 0 && !this.config.interactive) {
|
|
8285
|
+
return [responsePrompts.requireUseTool, undefined];
|
|
8286
|
+
}
|
|
8287
|
+
const finalResp = toolReponses.map(({ tool, response: response2 }) => responsePrompts.toolResults(tool, response2)).join(`
|
|
8288
|
+
|
|
8289
|
+
`);
|
|
8290
|
+
return [finalResp, undefined];
|
|
8291
|
+
}
|
|
8292
|
+
async#invokeTool(name, args) {
|
|
8293
|
+
try {
|
|
8294
|
+
const handler = this.handlers[name]?.handler;
|
|
8295
|
+
if (!handler) {
|
|
8296
|
+
return {
|
|
8297
|
+
type: "Error" /* Error */,
|
|
8298
|
+
message: responsePrompts.errorInvokeTool(name, "Tool not found"),
|
|
8299
|
+
canRetry: false
|
|
8300
|
+
};
|
|
8301
|
+
}
|
|
8302
|
+
return await handler(this.config.provider, args);
|
|
8303
|
+
} catch (error) {
|
|
8304
|
+
this.logger.debug(error, "Error invoking tool");
|
|
8305
|
+
return {
|
|
8306
|
+
type: "Error" /* Error */,
|
|
8307
|
+
message: responsePrompts.errorInvokeTool(name, error),
|
|
8308
|
+
canRetry: false
|
|
8309
|
+
};
|
|
8310
|
+
}
|
|
8311
|
+
}
|
|
8312
|
+
get model() {
|
|
8313
|
+
return this.ai.model;
|
|
8314
|
+
}
|
|
8315
|
+
}
|
|
8316
|
+
// src/tools/provider.ts
|
|
8317
|
+
class MockProvider {
|
|
8318
|
+
async readFile(path) {
|
|
8319
|
+
return "mock content";
|
|
8320
|
+
}
|
|
8321
|
+
async writeFile(path, content) {
|
|
8322
|
+
return;
|
|
8323
|
+
}
|
|
8324
|
+
async listFiles(path, recursive, maxCount) {
|
|
8325
|
+
return [["mock-file.txt"], false];
|
|
8326
|
+
}
|
|
8327
|
+
async searchFiles(path, regex, filePattern) {
|
|
8328
|
+
return ["mock-file.txt"];
|
|
8329
|
+
}
|
|
8330
|
+
async listCodeDefinitionNames(path) {
|
|
8331
|
+
return ["mockDefinition"];
|
|
8332
|
+
}
|
|
8333
|
+
async executeCommand(command, needApprove) {
|
|
8334
|
+
return { stdout: "mock output", stderr: "", exitCode: 0 };
|
|
8335
|
+
}
|
|
8336
|
+
async askFollowupQuestion(question, options) {
|
|
8337
|
+
return "mock answer";
|
|
8338
|
+
}
|
|
8339
|
+
async attemptCompletion(result) {
|
|
8340
|
+
return "mock completion";
|
|
8341
|
+
}
|
|
8342
|
+
}
|
|
8343
|
+
// src/tools/allTools.ts
|
|
8344
|
+
var exports_allTools = {};
|
|
8345
|
+
__export(exports_allTools, {
|
|
8346
|
+
writeToFile: () => writeToFile_default,
|
|
8347
|
+
searchFiles: () => searchFiles_default,
|
|
8348
|
+
replaceInFile: () => replaceInFile_default,
|
|
8349
|
+
readFile: () => readFile_default,
|
|
8350
|
+
listFiles: () => listFiles_default,
|
|
8351
|
+
listCodeDefinitionNames: () => listCodeDefinitionNames_default,
|
|
8352
|
+
executeCommand: () => executeCommand_default,
|
|
8353
|
+
attemptCompletion: () => attemptCompletion_default,
|
|
8354
|
+
askFollowupQuestion: () => askFollowupQuestion_default
|
|
8355
|
+
});
|
|
8356
|
+
|
|
8357
|
+
// src/tools/utils/replaceInFile.ts
|
|
8358
|
+
var replaceInFile = async (fileContent, diff) => {
|
|
8359
|
+
const blockPattern = /<<<<<+ SEARCH\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
|
|
8360
|
+
const blocks = [];
|
|
8361
|
+
for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
|
|
8362
|
+
blocks.push({ search: match[1], replace: match[2] });
|
|
8363
|
+
}
|
|
8364
|
+
if (blocks.length === 0) {
|
|
8365
|
+
throw new Error("No valid diff blocks found.");
|
|
8366
|
+
}
|
|
8367
|
+
const findAndReplace = (content, search, replace) => {
|
|
8368
|
+
let index = content.indexOf(search);
|
|
8369
|
+
if (index !== -1) {
|
|
8370
|
+
return content.slice(0, index) + replace + content.slice(index + search.length);
|
|
8371
|
+
}
|
|
8372
|
+
const trimmedSearch = search.trim();
|
|
8373
|
+
const trimmedContent = content.trim();
|
|
8374
|
+
const offset = content.indexOf(trimmedContent);
|
|
8375
|
+
index = trimmedContent.indexOf(trimmedSearch);
|
|
8376
|
+
if (index !== -1) {
|
|
8377
|
+
const absoluteIndex = offset + index;
|
|
8378
|
+
return content.slice(0, absoluteIndex) + replace + content.slice(absoluteIndex + trimmedSearch.length);
|
|
8379
|
+
}
|
|
8380
|
+
const normalizedSearch = trimmedSearch.replace(/\s+/g, " ");
|
|
8381
|
+
const normalizedContent = trimmedContent.replace(/\s+/g, " ");
|
|
8382
|
+
index = normalizedContent.indexOf(normalizedSearch);
|
|
8383
|
+
if (index !== -1) {
|
|
8384
|
+
let runningIndex = 0;
|
|
8385
|
+
let actualPos = offset;
|
|
8386
|
+
for (const segment of trimmedSearch.replace(/\s+/g, " ").split(" ")) {
|
|
8387
|
+
const segIndex = content.indexOf(segment, actualPos);
|
|
8388
|
+
if (segIndex === -1) {
|
|
8389
|
+
break;
|
|
8390
|
+
}
|
|
8391
|
+
if (runningIndex === 0) {
|
|
8392
|
+
actualPos = segIndex;
|
|
8393
|
+
} else {
|
|
8394
|
+
actualPos = segIndex + segment.length;
|
|
8395
|
+
}
|
|
8396
|
+
runningIndex++;
|
|
8397
|
+
}
|
|
8398
|
+
const strippedSearch = trimmedSearch.replace(/\s+/g, "");
|
|
8399
|
+
const endPos = actualPos;
|
|
8400
|
+
const startPos = endPos - strippedSearch.length;
|
|
8401
|
+
return content.slice(0, startPos) + replace + content.slice(endPos);
|
|
8402
|
+
}
|
|
8403
|
+
throw new Error(`Could not find the following text in file:
|
|
8404
|
+
${search}`);
|
|
8405
|
+
};
|
|
8406
|
+
let updatedFile = fileContent;
|
|
8407
|
+
for (const { search, replace } of blocks) {
|
|
8408
|
+
updatedFile = findAndReplace(updatedFile, search, replace);
|
|
8409
|
+
}
|
|
8410
|
+
return updatedFile;
|
|
8411
|
+
};
|
|
8412
|
+
// src/tools/utils/getArg.ts
|
|
8413
|
+
var getString = (args, name, defaultValue) => {
|
|
8414
|
+
const ret = args[name] ?? defaultValue;
|
|
8415
|
+
if (!ret) {
|
|
8416
|
+
throw new Error(`Missing required argument: ${name}`);
|
|
8417
|
+
}
|
|
8418
|
+
return ret;
|
|
8419
|
+
};
|
|
8420
|
+
var getStringArray = (args, name, defaultValue) => {
|
|
8421
|
+
const ret = args[name];
|
|
8422
|
+
if (!ret) {
|
|
8423
|
+
if (defaultValue === undefined) {
|
|
8424
|
+
throw new Error(`Missing required argument: ${name}`);
|
|
8020
8425
|
}
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
{
|
|
8031
|
-
name: "requires_approval",
|
|
8032
|
-
value: "false"
|
|
8033
|
-
}
|
|
8034
|
-
]
|
|
8426
|
+
return defaultValue;
|
|
8427
|
+
}
|
|
8428
|
+
return ret.split(",");
|
|
8429
|
+
};
|
|
8430
|
+
var getBoolean = (args, name, defaultValue) => {
|
|
8431
|
+
const ret = args[name];
|
|
8432
|
+
if (!ret) {
|
|
8433
|
+
if (defaultValue === undefined) {
|
|
8434
|
+
throw new Error(`Missing required argument: ${name}`);
|
|
8035
8435
|
}
|
|
8036
|
-
|
|
8436
|
+
return defaultValue;
|
|
8437
|
+
}
|
|
8438
|
+
switch (ret.toLowerCase()) {
|
|
8439
|
+
case "true":
|
|
8440
|
+
return true;
|
|
8441
|
+
case "false":
|
|
8442
|
+
return false;
|
|
8443
|
+
default:
|
|
8444
|
+
throw new Error(`Invalid argument value: ${name}`);
|
|
8445
|
+
}
|
|
8037
8446
|
};
|
|
8038
|
-
var
|
|
8039
|
-
name
|
|
8040
|
-
|
|
8447
|
+
var getInt = (args, name, defaultValue) => {
|
|
8448
|
+
const ret = args[name];
|
|
8449
|
+
if (!ret) {
|
|
8450
|
+
if (defaultValue === undefined) {
|
|
8451
|
+
throw new Error(`Missing required argument: ${name}`);
|
|
8452
|
+
}
|
|
8453
|
+
return defaultValue;
|
|
8454
|
+
}
|
|
8455
|
+
const parsed = Number.parseInt(ret);
|
|
8456
|
+
if (Number.isNaN(parsed)) {
|
|
8457
|
+
throw new Error(`Invalid argument value: ${name}`);
|
|
8458
|
+
}
|
|
8459
|
+
return parsed;
|
|
8460
|
+
};
|
|
8461
|
+
// src/tools/askFollowupQuestion.ts
|
|
8462
|
+
var toolInfo = {
|
|
8463
|
+
name: "ask_followup_question",
|
|
8464
|
+
description: "Whenever you need extra details or clarification to complete the task, pose a direct question to the user. Use this tool sparingly to avoid excessive back-and-forth. If helpful, offer multiple-choice options or examples to guide the user’s response.",
|
|
8041
8465
|
parameters: [
|
|
8042
8466
|
{
|
|
8043
|
-
name: "
|
|
8044
|
-
description: "The
|
|
8467
|
+
name: "question",
|
|
8468
|
+
description: "The question to ask the user. This should be a clear, specific question that addresses the information you need.",
|
|
8045
8469
|
required: true,
|
|
8046
|
-
usageValue: "
|
|
8470
|
+
usageValue: "Your question here"
|
|
8471
|
+
},
|
|
8472
|
+
{
|
|
8473
|
+
name: "options",
|
|
8474
|
+
description: "A comma separated list of possible answers to the question. If not provided, the user will be prompted to provide an answer.",
|
|
8475
|
+
required: false,
|
|
8476
|
+
usageValue: "A comma separated list of possible answers (optional)"
|
|
8047
8477
|
}
|
|
8048
8478
|
],
|
|
8049
8479
|
examples: [
|
|
8050
8480
|
{
|
|
8051
|
-
description: "Request to
|
|
8481
|
+
description: "Request to ask a question",
|
|
8052
8482
|
parameters: [
|
|
8053
8483
|
{
|
|
8054
|
-
name: "
|
|
8055
|
-
value: "
|
|
8484
|
+
name: "question",
|
|
8485
|
+
value: "What is the name of the project?"
|
|
8056
8486
|
}
|
|
8057
8487
|
]
|
|
8058
8488
|
},
|
|
8059
8489
|
{
|
|
8060
|
-
description: "Request to
|
|
8490
|
+
description: "Request to ask a question with options",
|
|
8061
8491
|
parameters: [
|
|
8062
8492
|
{
|
|
8063
|
-
name: "
|
|
8064
|
-
value: "
|
|
8493
|
+
name: "question",
|
|
8494
|
+
value: "What framework do you use?"
|
|
8495
|
+
},
|
|
8496
|
+
{
|
|
8497
|
+
name: "options",
|
|
8498
|
+
value: "React,Angular,Vue,Svelte"
|
|
8065
8499
|
}
|
|
8066
8500
|
]
|
|
8067
8501
|
}
|
|
8068
8502
|
]
|
|
8069
8503
|
};
|
|
8070
|
-
var
|
|
8071
|
-
|
|
8072
|
-
|
|
8504
|
+
var handler = async (provider, args) => {
|
|
8505
|
+
if (!provider.askFollowupQuestion) {
|
|
8506
|
+
return {
|
|
8507
|
+
type: "Error" /* Error */,
|
|
8508
|
+
message: "Not possible to ask followup question. Abort."
|
|
8509
|
+
};
|
|
8510
|
+
}
|
|
8511
|
+
const question = getString(args, "question");
|
|
8512
|
+
const options = getStringArray(args, "options", []);
|
|
8513
|
+
const answer = await provider.askFollowupQuestion(question, options);
|
|
8514
|
+
return {
|
|
8515
|
+
type: "Reply" /* Reply */,
|
|
8516
|
+
message: `<ask_followup_question_question>${question}</ask_followup_question_question>
|
|
8517
|
+
<ask_followup_question_answer>${answer}</ask_followup_question_answer>`
|
|
8518
|
+
};
|
|
8519
|
+
};
|
|
8520
|
+
var isAvailable = (provider) => {
|
|
8521
|
+
return !!provider.askFollowupQuestion;
|
|
8522
|
+
};
|
|
8523
|
+
var askFollowupQuestion_default = {
|
|
8524
|
+
...toolInfo,
|
|
8525
|
+
handler,
|
|
8526
|
+
isAvailable
|
|
8527
|
+
};
|
|
8528
|
+
// src/tools/attemptCompletion.ts
|
|
8529
|
+
var toolInfo2 = {
|
|
8530
|
+
name: "attempt_completion",
|
|
8531
|
+
description: "Use this tool when you believe the user’s requested task is complete. Indicate that your work is finished, but acknowledge the user may still provide additional instructions or questions if they want to continue.",
|
|
8073
8532
|
parameters: [
|
|
8074
8533
|
{
|
|
8075
|
-
name: "
|
|
8076
|
-
description: "The
|
|
8077
|
-
required: true,
|
|
8078
|
-
usageValue: "File path here"
|
|
8079
|
-
},
|
|
8080
|
-
{
|
|
8081
|
-
name: "content",
|
|
8082
|
-
description: "The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified.",
|
|
8534
|
+
name: "result",
|
|
8535
|
+
description: "The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.",
|
|
8083
8536
|
required: true,
|
|
8084
|
-
usageValue: "Your
|
|
8537
|
+
usageValue: "Your final result description here"
|
|
8085
8538
|
}
|
|
8086
8539
|
],
|
|
8087
8540
|
examples: [
|
|
8088
8541
|
{
|
|
8089
|
-
description: "Request to
|
|
8542
|
+
description: "Request to present the result of the task",
|
|
8090
8543
|
parameters: [
|
|
8091
8544
|
{
|
|
8092
|
-
name: "
|
|
8093
|
-
value: "
|
|
8094
|
-
},
|
|
8095
|
-
{
|
|
8096
|
-
name: "content",
|
|
8097
|
-
value: `import React from 'react';
|
|
8098
|
-
|
|
8099
|
-
function App() {
|
|
8100
|
-
return (
|
|
8101
|
-
<div>
|
|
8102
|
-
<h1>Hello, World!</h1>
|
|
8103
|
-
</div>
|
|
8104
|
-
);
|
|
8105
|
-
}
|
|
8106
|
-
|
|
8107
|
-
export default App;
|
|
8108
|
-
`
|
|
8545
|
+
name: "result",
|
|
8546
|
+
value: "Your final result description here"
|
|
8109
8547
|
}
|
|
8110
8548
|
]
|
|
8111
8549
|
}
|
|
8112
8550
|
]
|
|
8113
8551
|
};
|
|
8114
|
-
var
|
|
8115
|
-
|
|
8116
|
-
|
|
8552
|
+
var handler2 = async (provider, args) => {
|
|
8553
|
+
const result = getString(args, "result");
|
|
8554
|
+
const moreMessage = await provider.attemptCompletion?.(result);
|
|
8555
|
+
if (!moreMessage) {
|
|
8556
|
+
return {
|
|
8557
|
+
type: "Exit" /* Exit */,
|
|
8558
|
+
message: "<completed>true</completed>"
|
|
8559
|
+
};
|
|
8560
|
+
}
|
|
8561
|
+
return {
|
|
8562
|
+
type: "Reply" /* Reply */,
|
|
8563
|
+
message: `<user_message>${moreMessage}</user_message>`
|
|
8564
|
+
};
|
|
8565
|
+
};
|
|
8566
|
+
var isAvailable2 = (provider) => {
|
|
8567
|
+
return true;
|
|
8568
|
+
};
|
|
8569
|
+
var attemptCompletion_default = {
|
|
8570
|
+
...toolInfo2,
|
|
8571
|
+
handler: handler2,
|
|
8572
|
+
isAvailable: isAvailable2
|
|
8573
|
+
};
|
|
8574
|
+
// src/tools/executeCommand.ts
|
|
8575
|
+
var toolInfo3 = {
|
|
8576
|
+
name: "execute_command",
|
|
8577
|
+
description: `Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory.`,
|
|
8117
8578
|
parameters: [
|
|
8118
8579
|
{
|
|
8119
|
-
name: "
|
|
8120
|
-
description: "The
|
|
8580
|
+
name: "command",
|
|
8581
|
+
description: "The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.",
|
|
8121
8582
|
required: true,
|
|
8122
|
-
usageValue: "
|
|
8583
|
+
usageValue: "Your command here"
|
|
8123
8584
|
},
|
|
8124
8585
|
{
|
|
8125
|
-
name: "
|
|
8126
|
-
description: `
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
[exact content to find]
|
|
8130
|
-
=======
|
|
8131
|
-
[new content to replace with]
|
|
8132
|
-
>>>>>>> REPLACE
|
|
8133
|
-
\`\`\`
|
|
8134
|
-
Critical rules:
|
|
8135
|
-
1. SEARCH content must match the associated file section to find EXACTLY:
|
|
8136
|
-
* Match character-for-character including whitespace, indentation, line endings
|
|
8137
|
-
* Include all comments, docstrings, etc.
|
|
8138
|
-
2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
|
|
8139
|
-
* Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
|
|
8140
|
-
* Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
|
|
8141
|
-
* When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
|
|
8142
|
-
3. Keep SEARCH/REPLACE blocks concise:
|
|
8143
|
-
* Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
|
|
8144
|
-
* Include just the changing lines, and a few surrounding lines if needed for uniqueness.
|
|
8145
|
-
* Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
|
|
8146
|
-
* Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
|
|
8147
|
-
4. Special operations:
|
|
8148
|
-
* To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
|
|
8149
|
-
* To delete code: Use empty REPLACE section`,
|
|
8150
|
-
required: true,
|
|
8151
|
-
usageValue: "Search and replace blocks here"
|
|
8586
|
+
name: "requires_approval",
|
|
8587
|
+
description: `A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.`,
|
|
8588
|
+
required: false,
|
|
8589
|
+
usageValue: "true or false"
|
|
8152
8590
|
}
|
|
8153
8591
|
],
|
|
8154
8592
|
examples: [
|
|
8155
8593
|
{
|
|
8156
|
-
description: "Request to
|
|
8594
|
+
description: "Request to execute a command",
|
|
8157
8595
|
parameters: [
|
|
8158
8596
|
{
|
|
8159
|
-
name: "
|
|
8160
|
-
value: "
|
|
8597
|
+
name: "command",
|
|
8598
|
+
value: "npm run dev"
|
|
8161
8599
|
},
|
|
8162
8600
|
{
|
|
8163
|
-
name: "
|
|
8164
|
-
value:
|
|
8165
|
-
<<<<<<< SEARCH
|
|
8166
|
-
import React from 'react';
|
|
8167
|
-
=======
|
|
8168
|
-
import React, { useState } from 'react';
|
|
8169
|
-
>>>>>>> REPLACE
|
|
8170
|
-
|
|
8171
|
-
<<<<<<< SEARCH
|
|
8172
|
-
function handleSubmit() {
|
|
8173
|
-
saveData();
|
|
8174
|
-
setLoading(false);
|
|
8175
|
-
}
|
|
8176
|
-
|
|
8177
|
-
=======
|
|
8178
|
-
>>>>>>> REPLACE
|
|
8179
|
-
|
|
8180
|
-
<<<<<<< SEARCH
|
|
8181
|
-
return (
|
|
8182
|
-
<div>
|
|
8183
|
-
=======
|
|
8184
|
-
function handleSubmit() {
|
|
8185
|
-
saveData();
|
|
8186
|
-
setLoading(false);
|
|
8187
|
-
}
|
|
8188
|
-
|
|
8189
|
-
return (
|
|
8190
|
-
<div>
|
|
8191
|
-
>>>>>>> REPLACE
|
|
8192
|
-
`
|
|
8601
|
+
name: "requires_approval",
|
|
8602
|
+
value: "false"
|
|
8193
8603
|
}
|
|
8194
8604
|
]
|
|
8195
8605
|
}
|
|
8196
8606
|
]
|
|
8197
8607
|
};
|
|
8198
|
-
var
|
|
8199
|
-
|
|
8200
|
-
|
|
8608
|
+
var handler3 = async (provider, args) => {
|
|
8609
|
+
if (!provider.executeCommand) {
|
|
8610
|
+
return {
|
|
8611
|
+
type: "Error" /* Error */,
|
|
8612
|
+
message: "Not possible to execute command. Abort."
|
|
8613
|
+
};
|
|
8614
|
+
}
|
|
8615
|
+
const command = getString(args, "command");
|
|
8616
|
+
const requiresApproval = getBoolean(args, "requires_approval", false);
|
|
8617
|
+
const result = await provider.executeCommand?.(command, requiresApproval);
|
|
8618
|
+
const message = `<command>${command}</command>
|
|
8619
|
+
<command_exit_code>${result.exitCode}</command_exit_code>
|
|
8620
|
+
<command_stdout>
|
|
8621
|
+
${result.stdout}
|
|
8622
|
+
</command_stdout>
|
|
8623
|
+
<command_stderr>
|
|
8624
|
+
${result.stderr}
|
|
8625
|
+
</command_stderr>`;
|
|
8626
|
+
if (result.exitCode === 0) {
|
|
8627
|
+
return {
|
|
8628
|
+
type: "Reply" /* Reply */,
|
|
8629
|
+
message
|
|
8630
|
+
};
|
|
8631
|
+
}
|
|
8632
|
+
return {
|
|
8633
|
+
type: "Error" /* Error */,
|
|
8634
|
+
message
|
|
8635
|
+
};
|
|
8636
|
+
};
|
|
8637
|
+
var isAvailable3 = (provider) => {
|
|
8638
|
+
return !!provider.executeCommand;
|
|
8639
|
+
};
|
|
8640
|
+
var executeCommand_default = {
|
|
8641
|
+
...toolInfo3,
|
|
8642
|
+
handler: handler3,
|
|
8643
|
+
isAvailable: isAvailable3
|
|
8644
|
+
};
|
|
8645
|
+
// src/tools/listCodeDefinitionNames.ts
|
|
8646
|
+
var toolInfo4 = {
|
|
8647
|
+
name: "list_code_definition_names",
|
|
8648
|
+
description: "Request to list definition names (classes, functions, methods, etc.) used in a file. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.",
|
|
8201
8649
|
parameters: [
|
|
8202
8650
|
{
|
|
8203
8651
|
name: "path",
|
|
8204
|
-
description: "The path of
|
|
8652
|
+
description: "The path of a code file to list top level source code definitions for.",
|
|
8205
8653
|
required: true,
|
|
8206
8654
|
usageValue: "Directory path here"
|
|
8207
|
-
},
|
|
8208
|
-
{
|
|
8209
|
-
name: "regex",
|
|
8210
|
-
description: "The regular expression pattern to search for. Uses Rust regex syntax.",
|
|
8211
|
-
required: true,
|
|
8212
|
-
usageValue: "Your regex pattern here"
|
|
8213
|
-
},
|
|
8214
|
-
{
|
|
8215
|
-
name: "file_pattern",
|
|
8216
|
-
description: 'Glob pattern to filter files (e.g., "*.ts" for TypeScript files). If not provided, it will search all files (*).',
|
|
8217
|
-
required: false,
|
|
8218
|
-
usageValue: "file pattern here (optional)"
|
|
8219
|
-
}
|
|
8220
|
-
],
|
|
8221
|
-
examples: [
|
|
8222
|
-
{
|
|
8223
|
-
description: "Request to perform a regex search across files",
|
|
8224
|
-
parameters: [
|
|
8225
|
-
{
|
|
8226
|
-
name: "path",
|
|
8227
|
-
value: "src"
|
|
8228
|
-
},
|
|
8229
|
-
{
|
|
8230
|
-
name: "regex",
|
|
8231
|
-
value: "^src/components/"
|
|
8232
|
-
},
|
|
8233
|
-
{
|
|
8234
|
-
name: "file_pattern",
|
|
8235
|
-
value: "*.ts"
|
|
8236
|
-
}
|
|
8237
|
-
]
|
|
8238
8655
|
}
|
|
8239
8656
|
]
|
|
8240
8657
|
};
|
|
8241
|
-
var
|
|
8658
|
+
var handler4 = async (provider, args) => {
|
|
8659
|
+
if (!provider.listCodeDefinitionNames) {
|
|
8660
|
+
return {
|
|
8661
|
+
type: "Error" /* Error */,
|
|
8662
|
+
message: "Not possible to list code definition names. Abort."
|
|
8663
|
+
};
|
|
8664
|
+
}
|
|
8665
|
+
const path = getString(args, "path");
|
|
8666
|
+
const files = await provider.listCodeDefinitionNames(path);
|
|
8667
|
+
return {
|
|
8668
|
+
type: "Reply" /* Reply */,
|
|
8669
|
+
message: `<list_code_definition_names_path>${path}</list_code_definition_names_path>
|
|
8670
|
+
<list_code_definition_names_files>
|
|
8671
|
+
${files.join(`
|
|
8672
|
+
`)}
|
|
8673
|
+
</list_code_definition_names_files>`
|
|
8674
|
+
};
|
|
8675
|
+
};
|
|
8676
|
+
var isAvailable4 = (provider) => {
|
|
8677
|
+
return !!provider.listCodeDefinitionNames;
|
|
8678
|
+
};
|
|
8679
|
+
var listCodeDefinitionNames_default = {
|
|
8680
|
+
...toolInfo4,
|
|
8681
|
+
handler: handler4,
|
|
8682
|
+
isAvailable: isAvailable4
|
|
8683
|
+
};
|
|
8684
|
+
// src/tools/listFiles.ts
|
|
8685
|
+
var toolInfo5 = {
|
|
8242
8686
|
name: "list_files",
|
|
8243
8687
|
description: "Request to list files and directories within the specified directory. If recursive is true, it will list all files and directories recursively. If recursive is false or not provided, it will only list the top-level contents. Do not use this tool to confirm the existence of files you may have created, as the user will let you know if the files were created successfully or not.",
|
|
8244
8688
|
parameters: [
|
|
@@ -8249,10 +8693,16 @@ var listFiles = {
|
|
|
8249
8693
|
usageValue: "Directory path here"
|
|
8250
8694
|
},
|
|
8251
8695
|
{
|
|
8252
|
-
name: "
|
|
8253
|
-
description: "The
|
|
8696
|
+
name: "max_count",
|
|
8697
|
+
description: "The maximum number of files to list. Default to 2000",
|
|
8698
|
+
required: false,
|
|
8699
|
+
usageValue: "Maximum number of files to list (optional)"
|
|
8700
|
+
},
|
|
8701
|
+
{
|
|
8702
|
+
name: "recursive",
|
|
8703
|
+
description: "Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.",
|
|
8254
8704
|
required: false,
|
|
8255
|
-
usageValue: "
|
|
8705
|
+
usageValue: "true or false (optional)"
|
|
8256
8706
|
}
|
|
8257
8707
|
],
|
|
8258
8708
|
examples: [
|
|
@@ -8264,377 +8714,355 @@ var listFiles = {
|
|
|
8264
8714
|
value: "src"
|
|
8265
8715
|
},
|
|
8266
8716
|
{
|
|
8267
|
-
name: "
|
|
8268
|
-
value: "
|
|
8717
|
+
name: "max_count",
|
|
8718
|
+
value: "100"
|
|
8269
8719
|
}
|
|
8270
8720
|
]
|
|
8271
8721
|
}
|
|
8272
8722
|
]
|
|
8273
8723
|
};
|
|
8274
|
-
var
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
]
|
|
8724
|
+
var handler5 = async (provider, args) => {
|
|
8725
|
+
if (!provider.listFiles) {
|
|
8726
|
+
return {
|
|
8727
|
+
type: "Error" /* Error */,
|
|
8728
|
+
message: "Not possible to list files. Abort."
|
|
8729
|
+
};
|
|
8730
|
+
}
|
|
8731
|
+
const path = getString(args, "path");
|
|
8732
|
+
const maxCount = getInt(args, "max_count", 2000);
|
|
8733
|
+
const recursive = getBoolean(args, "recursive", true);
|
|
8734
|
+
const [files, limitReached] = await provider.listFiles(path, recursive, maxCount);
|
|
8735
|
+
return {
|
|
8736
|
+
type: "Reply" /* Reply */,
|
|
8737
|
+
message: `<list_files_path>${path}</list_files_path>
|
|
8738
|
+
<list_files_files>
|
|
8739
|
+
${files.join(`
|
|
8740
|
+
`)}
|
|
8741
|
+
</list_files_files>
|
|
8742
|
+
<list_files_truncated>${limitReached}</list_files_truncated>`
|
|
8743
|
+
};
|
|
8285
8744
|
};
|
|
8286
|
-
var
|
|
8287
|
-
|
|
8288
|
-
|
|
8745
|
+
var isAvailable5 = (provider) => {
|
|
8746
|
+
return !!provider.listFiles;
|
|
8747
|
+
};
|
|
8748
|
+
var listFiles_default = {
|
|
8749
|
+
...toolInfo5,
|
|
8750
|
+
handler: handler5,
|
|
8751
|
+
isAvailable: isAvailable5
|
|
8752
|
+
};
|
|
8753
|
+
// src/tools/readFile.ts
|
|
8754
|
+
var toolInfo6 = {
|
|
8755
|
+
name: "read_file",
|
|
8756
|
+
description: "Request to read the contents of one or multiple files at the specified paths. Use comma separated paths to read multiple files. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. May not be suitable for other types of binary files, as it returns the raw content as a string. Try to list all the potential files are relevent to the task, and then use this tool to read all the relevant files.",
|
|
8289
8757
|
parameters: [
|
|
8290
8758
|
{
|
|
8291
|
-
name: "
|
|
8292
|
-
description: "The
|
|
8759
|
+
name: "path",
|
|
8760
|
+
description: "The path of the file to read",
|
|
8293
8761
|
required: true,
|
|
8294
|
-
usageValue: "
|
|
8762
|
+
usageValue: "Comma separated paths here"
|
|
8295
8763
|
}
|
|
8296
8764
|
],
|
|
8297
8765
|
examples: [
|
|
8298
8766
|
{
|
|
8299
|
-
description: "Request to
|
|
8767
|
+
description: "Request to read the contents of a file",
|
|
8300
8768
|
parameters: [
|
|
8301
8769
|
{
|
|
8302
|
-
name: "
|
|
8303
|
-
value: "
|
|
8770
|
+
name: "path",
|
|
8771
|
+
value: "src/main.js"
|
|
8772
|
+
}
|
|
8773
|
+
]
|
|
8774
|
+
},
|
|
8775
|
+
{
|
|
8776
|
+
description: "Request to read multiple files",
|
|
8777
|
+
parameters: [
|
|
8778
|
+
{
|
|
8779
|
+
name: "path",
|
|
8780
|
+
value: "src/main.js,src/index.js"
|
|
8304
8781
|
}
|
|
8305
8782
|
]
|
|
8306
8783
|
}
|
|
8307
8784
|
]
|
|
8308
8785
|
};
|
|
8309
|
-
var
|
|
8310
|
-
|
|
8311
|
-
|
|
8786
|
+
var handler6 = async (provider, args) => {
|
|
8787
|
+
if (!provider.readFile) {
|
|
8788
|
+
return {
|
|
8789
|
+
type: "Error" /* Error */,
|
|
8790
|
+
message: "Not possible to read file. Abort."
|
|
8791
|
+
};
|
|
8792
|
+
}
|
|
8793
|
+
const paths = getStringArray(args, "path");
|
|
8794
|
+
const resp = [];
|
|
8795
|
+
for (const path of paths) {
|
|
8796
|
+
const fileContent = await provider.readFile(path);
|
|
8797
|
+
resp.push(`<read_file_file_conten path="${path}">${fileContent}</read_file_file_content>`);
|
|
8798
|
+
}
|
|
8799
|
+
return {
|
|
8800
|
+
type: "Reply" /* Reply */,
|
|
8801
|
+
message: resp.join(`
|
|
8802
|
+
`)
|
|
8803
|
+
};
|
|
8804
|
+
};
|
|
8805
|
+
var isAvailable6 = (provider) => {
|
|
8806
|
+
return !!provider.readFile;
|
|
8807
|
+
};
|
|
8808
|
+
var readFile_default = {
|
|
8809
|
+
...toolInfo6,
|
|
8810
|
+
handler: handler6,
|
|
8811
|
+
isAvailable: isAvailable6
|
|
8812
|
+
};
|
|
8813
|
+
// src/tools/replaceInFile.ts
|
|
8814
|
+
var toolInfo7 = {
|
|
8815
|
+
name: "replace_in_file",
|
|
8816
|
+
description: "Request to replace sections of content in an existing file using SEARCH/REPLACE blocks that define exact changes to specific parts of the file. This tool should be used when you need to make targeted changes to specific parts of a file.",
|
|
8312
8817
|
parameters: [
|
|
8313
8818
|
{
|
|
8314
|
-
name: "
|
|
8315
|
-
description: "The
|
|
8819
|
+
name: "path",
|
|
8820
|
+
description: "The path of the file to modify",
|
|
8316
8821
|
required: true,
|
|
8317
|
-
usageValue: "
|
|
8822
|
+
usageValue: "File path here"
|
|
8823
|
+
},
|
|
8824
|
+
{
|
|
8825
|
+
name: "diff",
|
|
8826
|
+
description: `One or more SEARCH/REPLACE blocks following this exact format:
|
|
8827
|
+
\`\`\`
|
|
8828
|
+
<<<<<<< SEARCH
|
|
8829
|
+
[exact content to find]
|
|
8830
|
+
=======
|
|
8831
|
+
[new content to replace with]
|
|
8832
|
+
>>>>>>> REPLACE
|
|
8833
|
+
\`\`\`
|
|
8834
|
+
Critical rules:
|
|
8835
|
+
1. SEARCH content must match the associated file section to find EXACTLY:
|
|
8836
|
+
* Match character-for-character including whitespace, indentation, line endings
|
|
8837
|
+
* Include all comments, docstrings, etc.
|
|
8838
|
+
2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
|
|
8839
|
+
* Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
|
|
8840
|
+
* Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
|
|
8841
|
+
* When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
|
|
8842
|
+
3. Keep SEARCH/REPLACE blocks concise:
|
|
8843
|
+
* Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
|
|
8844
|
+
* Include just the changing lines, and a few surrounding lines if needed for uniqueness.
|
|
8845
|
+
* Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
|
|
8846
|
+
* Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
|
|
8847
|
+
4. Special operations:
|
|
8848
|
+
* To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
|
|
8849
|
+
* To delete code: Use empty REPLACE section`,
|
|
8850
|
+
required: true,
|
|
8851
|
+
usageValue: "Search and replace blocks here"
|
|
8318
8852
|
}
|
|
8319
8853
|
],
|
|
8320
8854
|
examples: [
|
|
8321
8855
|
{
|
|
8322
|
-
description: "Request to
|
|
8856
|
+
description: "Request to replace sections of content in a file",
|
|
8323
8857
|
parameters: [
|
|
8324
8858
|
{
|
|
8325
|
-
name: "
|
|
8326
|
-
value: "
|
|
8327
|
-
}
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
const toolTags = tools2.map((tool) => `${toolNamePrefix}${tool.name}`);
|
|
8337
|
-
const toolPattern = toolTags.join("|");
|
|
8338
|
-
const tagRegex = new RegExp(`<(${toolPattern})>(.*)<\\/\\1>`, "s");
|
|
8339
|
-
const match = assistantMessage.match(tagRegex);
|
|
8340
|
-
if (match) {
|
|
8341
|
-
const beforeTag = assistantMessage.slice(0, match.index).trim();
|
|
8342
|
-
const fullTagContent = match[0];
|
|
8343
|
-
if (beforeTag) {
|
|
8344
|
-
results.push({
|
|
8345
|
-
type: "text",
|
|
8346
|
-
content: beforeTag
|
|
8347
|
-
});
|
|
8348
|
-
}
|
|
8349
|
-
const tagName = match[1];
|
|
8350
|
-
const toolName = tagName.replace(toolNamePrefix, "");
|
|
8351
|
-
const tool = tools2.find((t) => t.name === toolName);
|
|
8352
|
-
if (tool) {
|
|
8353
|
-
const params = {};
|
|
8354
|
-
for (const param of tool.parameters) {
|
|
8355
|
-
const paramName = `${parameterPrefix}${param.name}`;
|
|
8356
|
-
const escapedParamName = paramName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8357
|
-
const paramPattern = `<${escapedParamName}>([\\s\\S]*?)<\\/${escapedParamName}>`;
|
|
8358
|
-
const paramMatch = fullTagContent.match(new RegExp(paramPattern, "s"));
|
|
8359
|
-
if (paramMatch) {
|
|
8360
|
-
params[param.name] = paramMatch[1].trim();
|
|
8361
|
-
}
|
|
8362
|
-
}
|
|
8363
|
-
results.push({
|
|
8364
|
-
type: "tool_use",
|
|
8365
|
-
name: toolName,
|
|
8366
|
-
params
|
|
8367
|
-
});
|
|
8368
|
-
} else {
|
|
8369
|
-
results.push({
|
|
8370
|
-
type: "text",
|
|
8371
|
-
content: fullTagContent
|
|
8372
|
-
});
|
|
8373
|
-
}
|
|
8374
|
-
const afterTag = assistantMessage.slice((match.index ?? 0) + fullTagContent.length).trim();
|
|
8375
|
-
if (afterTag) {
|
|
8376
|
-
results.push({
|
|
8377
|
-
type: "text",
|
|
8378
|
-
content: afterTag
|
|
8379
|
-
});
|
|
8380
|
-
}
|
|
8381
|
-
} else {
|
|
8382
|
-
results.push({
|
|
8383
|
-
type: "text",
|
|
8384
|
-
content: assistantMessage
|
|
8385
|
-
});
|
|
8386
|
-
}
|
|
8387
|
-
return results;
|
|
8388
|
-
}
|
|
8389
|
-
|
|
8390
|
-
// src/Agent/prompts.ts
|
|
8391
|
-
var toolInfoPrompt = (tool, toolNamePrefix, parameterPrefix) => `
|
|
8392
|
-
## ${toolNamePrefix}${tool.name}
|
|
8393
|
-
|
|
8394
|
-
Description: ${tool.description}
|
|
8395
|
-
|
|
8396
|
-
Parameters:
|
|
8397
|
-
${tool.parameters.map((param) => `- ${parameterPrefix}${param.name}: (${param.required ? "required" : "optional"}) ${param.description}`).join(`
|
|
8398
|
-
`)}
|
|
8399
|
-
|
|
8400
|
-
Usage:
|
|
8401
|
-
<${toolNamePrefix}${tool.name}>
|
|
8402
|
-
${tool.parameters.map((param) => `<${parameterPrefix}${param.name}>${param.usageValue}</${parameterPrefix}${param.name}>`).join(`
|
|
8403
|
-
`)}
|
|
8404
|
-
</${toolNamePrefix}${tool.name}>`;
|
|
8405
|
-
var toolInfoExamplesPrompt = (idx, tool, example, toolNamePrefix, parameterPrefix) => `
|
|
8406
|
-
## Example ${idx + 1}: ${example.description}
|
|
8407
|
-
|
|
8408
|
-
<${toolNamePrefix}${tool.name}>
|
|
8409
|
-
${example.parameters.map((param) => `<${parameterPrefix}${param.name}>${param.value}</${parameterPrefix}${param.name}>`).join(`
|
|
8410
|
-
`)}
|
|
8411
|
-
</${toolNamePrefix}${tool.name}>
|
|
8412
|
-
`;
|
|
8413
|
-
var toolUsePrompt = (tools2, toolNamePrefix) => {
|
|
8414
|
-
if (tools2.length === 0) {
|
|
8415
|
-
return "";
|
|
8416
|
-
}
|
|
8417
|
-
const parameterPrefix = `${toolNamePrefix}parameter_`;
|
|
8418
|
-
let exampleIndex = 0;
|
|
8419
|
-
return `
|
|
8420
|
-
====
|
|
8421
|
-
|
|
8422
|
-
TOOL USE
|
|
8423
|
-
|
|
8424
|
-
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
|
8425
|
-
|
|
8426
|
-
# Tool Use Formatting
|
|
8427
|
-
|
|
8428
|
-
Tool use is formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:
|
|
8429
|
-
|
|
8430
|
-
<${toolNamePrefix}tool_name>
|
|
8431
|
-
<${parameterPrefix}name1>value1</${parameterPrefix}name1>
|
|
8432
|
-
<${parameterPrefix}name2>value2</${parameterPrefix}name2>
|
|
8433
|
-
...
|
|
8434
|
-
</${toolNamePrefix}tool_name>
|
|
8435
|
-
|
|
8436
|
-
For example:
|
|
8437
|
-
|
|
8438
|
-
<${toolNamePrefix}read_file>
|
|
8439
|
-
<${parameterPrefix}path>src/main.js</${parameterPrefix}path>
|
|
8440
|
-
</${toolNamePrefix}read_file>
|
|
8441
|
-
|
|
8442
|
-
Always adhere to this format for the tool use to ensure proper parsing and execution.
|
|
8443
|
-
|
|
8444
|
-
# Tools
|
|
8445
|
-
${tools2.map((tool) => toolInfoPrompt(tool, toolNamePrefix, parameterPrefix)).join(`
|
|
8446
|
-
`)}
|
|
8447
|
-
|
|
8448
|
-
# Tool Use Examples
|
|
8449
|
-
${tools2.map((tool) => {
|
|
8450
|
-
let promp = "";
|
|
8451
|
-
for (const example of tool.examples ?? []) {
|
|
8452
|
-
promp += toolInfoExamplesPrompt(exampleIndex++, tool, example, toolNamePrefix, parameterPrefix);
|
|
8453
|
-
}
|
|
8454
|
-
return promp;
|
|
8455
|
-
}).join("")}
|
|
8456
|
-
# Tool Use Guidelines
|
|
8859
|
+
name: "path",
|
|
8860
|
+
value: "src/main.js"
|
|
8861
|
+
},
|
|
8862
|
+
{
|
|
8863
|
+
name: "diff",
|
|
8864
|
+
value: `
|
|
8865
|
+
<<<<<<< SEARCH
|
|
8866
|
+
import React from 'react';
|
|
8867
|
+
=======
|
|
8868
|
+
import React, { useState } from 'react';
|
|
8869
|
+
>>>>>>> REPLACE
|
|
8457
8870
|
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
- Tool success or failure details
|
|
8464
|
-
- Linter errors
|
|
8465
|
-
- Terminal output or other relevant feedback
|
|
8466
|
-
6. **Never repeat or quote the entire tool command** in your final user-facing message. Summarize outcomes clearly and avoid echoing commands verbatim.
|
|
8467
|
-
7. **Respond concisely** and move the conversation forward. Do not re-issue the same command or re-trigger tool use without necessity.
|
|
8468
|
-
8. Follow these steps **iteratively**, confirming success and addressing issues as you go.
|
|
8871
|
+
<<<<<<< SEARCH
|
|
8872
|
+
function handleSubmit() {
|
|
8873
|
+
saveData();
|
|
8874
|
+
setLoading(false);
|
|
8875
|
+
}
|
|
8469
8876
|
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
- You confirm each step’s results before proceeding.
|
|
8473
|
-
- You provide only the necessary information in user-facing replies to prevent re-interpretation as new commands.`;
|
|
8474
|
-
};
|
|
8475
|
-
var responsePrompts = {
|
|
8476
|
-
errorInvokeTool: (tool, error) => `An error occurred while invoking the tool "${tool}": ${error}`,
|
|
8477
|
-
requireUseTool: "Error: You must use a tool before proceeding",
|
|
8478
|
-
toolResults: (tool, result) => `<tool_response>
|
|
8479
|
-
<tool_name>${tool}</tool_name>
|
|
8480
|
-
<tool_result>
|
|
8481
|
-
${result}
|
|
8482
|
-
</tool_result>
|
|
8483
|
-
</tool_response>`
|
|
8484
|
-
};
|
|
8877
|
+
=======
|
|
8878
|
+
>>>>>>> REPLACE
|
|
8485
8879
|
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8880
|
+
<<<<<<< SEARCH
|
|
8881
|
+
return (
|
|
8882
|
+
<div>
|
|
8883
|
+
=======
|
|
8884
|
+
function handleSubmit() {
|
|
8885
|
+
saveData();
|
|
8886
|
+
setLoading(false);
|
|
8887
|
+
}
|
|
8888
|
+
|
|
8889
|
+
return (
|
|
8890
|
+
<div>
|
|
8891
|
+
>>>>>>> REPLACE
|
|
8892
|
+
`
|
|
8893
|
+
}
|
|
8894
|
+
]
|
|
8501
8895
|
}
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
outputTokens: 0,
|
|
8510
|
-
cacheWriteTokens: 0,
|
|
8511
|
-
cacheReadTokens: 0,
|
|
8512
|
-
totalCost: 0
|
|
8896
|
+
]
|
|
8897
|
+
};
|
|
8898
|
+
var handler7 = async (provider, args) => {
|
|
8899
|
+
if (!provider.readFile || !provider.writeFile) {
|
|
8900
|
+
return {
|
|
8901
|
+
type: "Error" /* Error */,
|
|
8902
|
+
message: "Not possible to replace in file. Abort."
|
|
8513
8903
|
};
|
|
8514
|
-
let text = `<task>${task}</task>`;
|
|
8515
|
-
if (context) {
|
|
8516
|
-
text += `
|
|
8517
|
-
<context>${context}</context>`;
|
|
8518
|
-
}
|
|
8519
|
-
let nextRequest = [
|
|
8520
|
-
{
|
|
8521
|
-
type: "text",
|
|
8522
|
-
text
|
|
8523
|
-
}
|
|
8524
|
-
];
|
|
8525
|
-
let iterations = 0;
|
|
8526
|
-
while (nextRequest) {
|
|
8527
|
-
if (iterations >= taskInfo.options.maxIterations) {
|
|
8528
|
-
callback({ kind: "max_iterations_reached", info: taskInfo });
|
|
8529
|
-
break;
|
|
8530
|
-
}
|
|
8531
|
-
const response = await this.#request(taskInfo, nextRequest, callback);
|
|
8532
|
-
nextRequest = await this.#handleResponse(taskInfo, response, callback);
|
|
8533
|
-
++iterations;
|
|
8534
|
-
}
|
|
8535
|
-
callback({ kind: "end_task", info: taskInfo });
|
|
8536
|
-
return taskInfo;
|
|
8537
8904
|
}
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8905
|
+
const path = getString(args, "path");
|
|
8906
|
+
const diff = getString(args, "diff");
|
|
8907
|
+
const fileContent = await provider.readFile(path);
|
|
8908
|
+
const result = await replaceInFile(fileContent, diff);
|
|
8909
|
+
await provider.writeFile(path, result);
|
|
8910
|
+
return {
|
|
8911
|
+
type: "Reply" /* Reply */,
|
|
8912
|
+
message: `<replace_in_file_path>${path}</replace_in_file_path>`
|
|
8913
|
+
};
|
|
8914
|
+
};
|
|
8915
|
+
var isAvailable7 = (provider) => {
|
|
8916
|
+
return !!provider.readFile && !!provider.writeFile;
|
|
8917
|
+
};
|
|
8918
|
+
var replaceInFile_default = {
|
|
8919
|
+
...toolInfo7,
|
|
8920
|
+
handler: handler7,
|
|
8921
|
+
isAvailable: isAvailable7
|
|
8922
|
+
};
|
|
8923
|
+
// src/tools/searchFiles.ts
|
|
8924
|
+
var toolInfo8 = {
|
|
8925
|
+
name: "search_files",
|
|
8926
|
+
description: "Request to perform a regex search across files in a specified directory, outputting context-rich results that include surrounding lines. This tool searches for patterns or specific content across multiple files, displaying each match with encapsulating context.",
|
|
8927
|
+
parameters: [
|
|
8928
|
+
{
|
|
8929
|
+
name: "path",
|
|
8930
|
+
description: "The path of the directory to search in (relative to the current working directory). This directory will be recursively searched.",
|
|
8931
|
+
required: true,
|
|
8932
|
+
usageValue: "Directory path here"
|
|
8933
|
+
},
|
|
8934
|
+
{
|
|
8935
|
+
name: "regex",
|
|
8936
|
+
description: "The regular expression pattern to search for. Uses Rust regex syntax.",
|
|
8937
|
+
required: true,
|
|
8938
|
+
usageValue: "Your regex pattern here"
|
|
8939
|
+
},
|
|
8940
|
+
{
|
|
8941
|
+
name: "file_pattern",
|
|
8942
|
+
description: 'Glob pattern to filter files (e.g., "*.ts" for TypeScript files). If not provided, it will search all files (*).',
|
|
8943
|
+
required: false,
|
|
8944
|
+
usageValue: "file pattern here (optional)"
|
|
8562
8945
|
}
|
|
8563
|
-
|
|
8564
|
-
|
|
8946
|
+
],
|
|
8947
|
+
examples: [
|
|
8948
|
+
{
|
|
8949
|
+
description: "Request to perform a regex search across files",
|
|
8950
|
+
parameters: [
|
|
8951
|
+
{
|
|
8952
|
+
name: "path",
|
|
8953
|
+
value: "src"
|
|
8954
|
+
},
|
|
8955
|
+
{
|
|
8956
|
+
name: "regex",
|
|
8957
|
+
value: "^components/"
|
|
8958
|
+
},
|
|
8959
|
+
{
|
|
8960
|
+
name: "file_pattern",
|
|
8961
|
+
value: "*.ts"
|
|
8962
|
+
}
|
|
8963
|
+
]
|
|
8565
8964
|
}
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8965
|
+
]
|
|
8966
|
+
};
|
|
8967
|
+
var handler8 = async (provider, args) => {
|
|
8968
|
+
if (!provider.searchFiles) {
|
|
8969
|
+
return {
|
|
8970
|
+
type: "Error" /* Error */,
|
|
8971
|
+
message: "Not possible to search files. Abort."
|
|
8972
|
+
};
|
|
8573
8973
|
}
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8974
|
+
const path = getString(args, "path");
|
|
8975
|
+
const regex = getString(args, "regex");
|
|
8976
|
+
const filePattern = getString(args, "file_pattern", "*");
|
|
8977
|
+
const files = await provider.searchFiles(path, regex, filePattern);
|
|
8978
|
+
return {
|
|
8979
|
+
type: "Reply" /* Reply */,
|
|
8980
|
+
message: `<search_files_path>${path}</search_files_path>
|
|
8981
|
+
<search_files_regex>${regex}</search_files_regex>
|
|
8982
|
+
<search_files_file_pattern>${filePattern}</search_files_file_pattern>
|
|
8983
|
+
<search_files_files>
|
|
8984
|
+
${files.join(`
|
|
8985
|
+
`)}
|
|
8986
|
+
</search_files_files>
|
|
8987
|
+
`
|
|
8988
|
+
};
|
|
8989
|
+
};
|
|
8990
|
+
var isAvailable8 = (provider) => {
|
|
8991
|
+
return !!provider.searchFiles;
|
|
8992
|
+
};
|
|
8993
|
+
var searchFiles_default = {
|
|
8994
|
+
...toolInfo8,
|
|
8995
|
+
handler: handler8,
|
|
8996
|
+
isAvailable: isAvailable8
|
|
8997
|
+
};
|
|
8998
|
+
// src/tools/writeToFile.ts
|
|
8999
|
+
var toolInfo9 = {
|
|
9000
|
+
name: "write_to_file",
|
|
9001
|
+
description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file.",
|
|
9002
|
+
parameters: [
|
|
9003
|
+
{
|
|
9004
|
+
name: "path",
|
|
9005
|
+
description: "The path of the file to write to",
|
|
9006
|
+
required: true,
|
|
9007
|
+
usageValue: "File path here"
|
|
9008
|
+
},
|
|
9009
|
+
{
|
|
9010
|
+
name: "content",
|
|
9011
|
+
description: "The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified.",
|
|
9012
|
+
required: true,
|
|
9013
|
+
usageValue: "Your file content here"
|
|
8605
9014
|
}
|
|
8606
|
-
|
|
8607
|
-
|
|
9015
|
+
],
|
|
9016
|
+
examples: [
|
|
9017
|
+
{
|
|
9018
|
+
description: "Request to write content to a file",
|
|
9019
|
+
parameters: [
|
|
8608
9020
|
{
|
|
8609
|
-
|
|
8610
|
-
|
|
9021
|
+
name: "path",
|
|
9022
|
+
value: "src/main.js"
|
|
9023
|
+
},
|
|
9024
|
+
{
|
|
9025
|
+
name: "content",
|
|
9026
|
+
value: `import React from 'react';
|
|
9027
|
+
|
|
9028
|
+
function App() {
|
|
9029
|
+
return (
|
|
9030
|
+
<div>
|
|
9031
|
+
<h1>Hello, World!</h1>
|
|
9032
|
+
</div>
|
|
9033
|
+
);
|
|
9034
|
+
}
|
|
9035
|
+
|
|
9036
|
+
export default App;
|
|
9037
|
+
`
|
|
8611
9038
|
}
|
|
8612
|
-
]
|
|
8613
|
-
}
|
|
8614
|
-
const finalResp = toolReponses.map(({ tool, response: response2 }) => responsePrompts.toolResults(tool, response2)).join(`
|
|
8615
|
-
`);
|
|
8616
|
-
return [
|
|
8617
|
-
{
|
|
8618
|
-
type: "text",
|
|
8619
|
-
text: finalResp
|
|
8620
|
-
}
|
|
8621
|
-
];
|
|
8622
|
-
}
|
|
8623
|
-
async#invokeTool(name, args) {
|
|
8624
|
-
try {
|
|
8625
|
-
return await this.config.toolHandler(name, args);
|
|
8626
|
-
} catch (error) {
|
|
8627
|
-
return {
|
|
8628
|
-
type: "Error" /* Error */,
|
|
8629
|
-
message: responsePrompts.errorInvokeTool(name, error),
|
|
8630
|
-
canRetry: false
|
|
8631
|
-
};
|
|
9039
|
+
]
|
|
8632
9040
|
}
|
|
9041
|
+
]
|
|
9042
|
+
};
|
|
9043
|
+
var handler9 = async (provider, args) => {
|
|
9044
|
+
if (!provider.writeFile) {
|
|
9045
|
+
return {
|
|
9046
|
+
type: "Error" /* Error */,
|
|
9047
|
+
message: "Not possible to write file. Abort."
|
|
9048
|
+
};
|
|
8633
9049
|
}
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
9050
|
+
const path = getString(args, "path");
|
|
9051
|
+
const content = getString(args, "content");
|
|
9052
|
+
await provider.writeFile(path, content);
|
|
9053
|
+
return {
|
|
9054
|
+
type: "Reply" /* Reply */,
|
|
9055
|
+
message: `<write_file_path>${path}</write_file_path><status>Success</status>`
|
|
9056
|
+
};
|
|
9057
|
+
};
|
|
9058
|
+
var isAvailable9 = (provider) => {
|
|
9059
|
+
return !!provider.writeFile;
|
|
9060
|
+
};
|
|
9061
|
+
var writeToFile_default = {
|
|
9062
|
+
...toolInfo9,
|
|
9063
|
+
handler: handler9,
|
|
9064
|
+
isAvailable: isAvailable9
|
|
9065
|
+
};
|
|
8638
9066
|
// src/Agent/CoderAgent/prompts.ts
|
|
8639
9067
|
var basePrompt = "You are a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.";
|
|
8640
9068
|
var editingFilesPrompt = (toolNamePrefix) => `
|
|
@@ -8716,7 +9144,7 @@ RULES
|
|
|
8716
9144
|
|
|
8717
9145
|
- You may use \`cd\` to enter any child directory within the current working directory. For example, \`cd myChildDir\`. But you may never move to a parent directory or any directory outside your current path. For example, do not use \`cd ..\`, \`cd /\`, or any absolute path.
|
|
8718
9146
|
- Always work with relative path names, and never use absolute paths.
|
|
8719
|
-
- When generating code file, add a comment on top of the file
|
|
9147
|
+
- When generating code or test or any file that support comments, add a comment on top of the file with a description of the file's purpose and a note that this file is generated by "polka.codes".
|
|
8720
9148
|
- When generate text file such as README.md, add a footer indicating this file is generated by "polka.codes".
|
|
8721
9149
|
- Before using the ${toolNamePrefix}execute_command tool, you must first think about the SYSTEM INFORMATION context provided to understand the user's environment and tailor your commands to ensure they are compatible with their system. You must also consider if the command you need to run should be executed in a specific directory outside of the current working directory, and if so prepend with \`cd\`'ing into that directory && then executing the command (as one command). For example, if you needed to run \`npm install\` in a project that's not in the current working directory, you would need to prepend with a \`cd\` i.e. pseudocode for this would be \`cd (path to project) && (command, in this case npm install)\`. However, you can only cd into child directory, but never parent directory or root directory or home directory.
|
|
8722
9150
|
- When using the ${toolNamePrefix}search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the ${toolNamePrefix}search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use ${toolNamePrefix}read_file to examine the full context of interesting matches before using ${toolNamePrefix}replace_in_file to make informed changes.
|
|
@@ -8789,9 +9217,27 @@ The following additional commands are provided by the user, and should be follow
|
|
|
8789
9217
|
|
|
8790
9218
|
${joined}`;
|
|
8791
9219
|
};
|
|
8792
|
-
var
|
|
9220
|
+
var interactiveMode = (interactive) => {
|
|
9221
|
+
if (interactive) {
|
|
9222
|
+
return `
|
|
9223
|
+
====
|
|
9224
|
+
|
|
9225
|
+
INTERACTIVE MODE
|
|
9226
|
+
|
|
9227
|
+
You are in interactive mode. This means you may ask user questions to gather additional information to complete the task.
|
|
9228
|
+
`;
|
|
9229
|
+
}
|
|
9230
|
+
return `
|
|
9231
|
+
====
|
|
9232
|
+
|
|
9233
|
+
NON-INTERACTIVE MODE
|
|
9234
|
+
|
|
9235
|
+
You are in non-interactive mode. This means you will not be able to ask user questions to gather additional information to complete the task. You should try to use available tools to accomplish the task. If unable to precede further, you may try to end the task and provide a reason.
|
|
9236
|
+
`;
|
|
9237
|
+
};
|
|
9238
|
+
var fullSystemPrompt = (info, tools, toolNamePrefix, instructions, commands, interactive) => `
|
|
8793
9239
|
${basePrompt}
|
|
8794
|
-
${toolUsePrompt(
|
|
9240
|
+
${toolUsePrompt(tools, toolNamePrefix)}
|
|
8795
9241
|
${editingFilesPrompt(toolNamePrefix)}
|
|
8796
9242
|
${capabilities(toolNamePrefix)}
|
|
8797
9243
|
${rules(toolNamePrefix)}
|
|
@@ -8799,52 +9245,45 @@ ${objectives(toolNamePrefix)}
|
|
|
8799
9245
|
${systemInformation(info)}
|
|
8800
9246
|
${customInstructions(instructions)}
|
|
8801
9247
|
${customCommands(commands)}
|
|
9248
|
+
${interactiveMode(interactive)}
|
|
8802
9249
|
`;
|
|
8803
9250
|
|
|
8804
9251
|
// src/Agent/CoderAgent/index.ts
|
|
8805
|
-
var defaultTools = [
|
|
8806
|
-
exports_tools.executeCommand,
|
|
8807
|
-
exports_tools.readFile,
|
|
8808
|
-
exports_tools.writeToFile,
|
|
8809
|
-
exports_tools.replaceInFile,
|
|
8810
|
-
exports_tools.searchFiles,
|
|
8811
|
-
exports_tools.listFiles,
|
|
8812
|
-
exports_tools.listCodeDefinitionNames,
|
|
8813
|
-
exports_tools.attemptCompletion
|
|
8814
|
-
];
|
|
8815
|
-
|
|
8816
9252
|
class CoderAgent extends AgentBase {
|
|
8817
9253
|
constructor(options) {
|
|
8818
|
-
const
|
|
9254
|
+
const combinedTools = [...options.additionalTools ?? [], ...Object.values(exports_allTools)];
|
|
9255
|
+
const tools = getAvailableTools(options.provider, combinedTools);
|
|
8819
9256
|
const toolNamePrefix = "tool_";
|
|
8820
9257
|
const systemPrompt = fullSystemPrompt({
|
|
8821
9258
|
os: options.os
|
|
8822
|
-
},
|
|
9259
|
+
}, tools, toolNamePrefix, options.customInstructions ?? [], options.commands ?? {}, options.interactive);
|
|
8823
9260
|
super(options.ai, {
|
|
8824
9261
|
systemPrompt,
|
|
8825
|
-
tools
|
|
9262
|
+
tools,
|
|
8826
9263
|
toolNamePrefix,
|
|
8827
|
-
|
|
8828
|
-
|
|
9264
|
+
provider: options.provider,
|
|
9265
|
+
interactive: options.interactive
|
|
8829
9266
|
}, createServiceLogger("CoderAgent"));
|
|
8830
9267
|
}
|
|
8831
9268
|
}
|
|
8832
9269
|
export {
|
|
8833
|
-
writeToFile,
|
|
9270
|
+
writeToFile_default as writeToFile,
|
|
8834
9271
|
setLogger,
|
|
8835
|
-
searchFiles,
|
|
8836
|
-
replaceInFile,
|
|
8837
|
-
readFile,
|
|
8838
|
-
listFiles,
|
|
8839
|
-
listCodeDefinitionNames,
|
|
9272
|
+
searchFiles_default as searchFiles,
|
|
9273
|
+
replaceInFile_default as replaceInFile,
|
|
9274
|
+
readFile_default as readFile,
|
|
9275
|
+
listFiles_default as listFiles,
|
|
9276
|
+
listCodeDefinitionNames_default as listCodeDefinitionNames,
|
|
8840
9277
|
getLogger,
|
|
8841
|
-
executeCommand,
|
|
9278
|
+
executeCommand_default as executeCommand,
|
|
9279
|
+
defaultModels,
|
|
8842
9280
|
createServiceLogger,
|
|
8843
9281
|
createService,
|
|
8844
|
-
attemptCompletion,
|
|
8845
|
-
askFollowupQuestion,
|
|
8846
|
-
|
|
8847
|
-
|
|
9282
|
+
attemptCompletion_default as attemptCompletion,
|
|
9283
|
+
askFollowupQuestion_default as askFollowupQuestion,
|
|
9284
|
+
exports_allTools as allTools,
|
|
9285
|
+
MockProvider,
|
|
9286
|
+
ExitReason,
|
|
8848
9287
|
CoderAgent,
|
|
8849
9288
|
AiServiceProvider,
|
|
8850
9289
|
AgentBase
|