@polka-codes/runner 0.8.11 → 0.8.13

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.
Files changed (2) hide show
  1. package/dist/index.js +489 -243
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31282,9 +31282,9 @@ var require_event_target = __commonJS((exports, module) => {
31282
31282
  }
31283
31283
  Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true });
31284
31284
  var EventTarget = {
31285
- addEventListener(type, handler14, options = {}) {
31285
+ addEventListener(type, handler15, options = {}) {
31286
31286
  for (const listener of this.listeners(type)) {
31287
- if (!options[kForOnEventAttribute] && listener[kListener] === handler14 && !listener[kForOnEventAttribute]) {
31287
+ if (!options[kForOnEventAttribute] && listener[kListener] === handler15 && !listener[kForOnEventAttribute]) {
31288
31288
  return;
31289
31289
  }
31290
31290
  }
@@ -31295,7 +31295,7 @@ var require_event_target = __commonJS((exports, module) => {
31295
31295
  data: isBinary ? data : data.toString()
31296
31296
  });
31297
31297
  event[kTarget] = this;
31298
- callListener(handler14, this, event);
31298
+ callListener(handler15, this, event);
31299
31299
  };
31300
31300
  } else if (type === "close") {
31301
31301
  wrapper = function onClose(code, message) {
@@ -31305,7 +31305,7 @@ var require_event_target = __commonJS((exports, module) => {
31305
31305
  wasClean: this._closeFrameReceived && this._closeFrameSent
31306
31306
  });
31307
31307
  event[kTarget] = this;
31308
- callListener(handler14, this, event);
31308
+ callListener(handler15, this, event);
31309
31309
  };
31310
31310
  } else if (type === "error") {
31311
31311
  wrapper = function onError(error) {
@@ -31314,28 +31314,28 @@ var require_event_target = __commonJS((exports, module) => {
31314
31314
  message: error.message
31315
31315
  });
31316
31316
  event[kTarget] = this;
31317
- callListener(handler14, this, event);
31317
+ callListener(handler15, this, event);
31318
31318
  };
31319
31319
  } else if (type === "open") {
31320
31320
  wrapper = function onOpen() {
31321
31321
  const event = new Event("open");
31322
31322
  event[kTarget] = this;
31323
- callListener(handler14, this, event);
31323
+ callListener(handler15, this, event);
31324
31324
  };
31325
31325
  } else {
31326
31326
  return;
31327
31327
  }
31328
31328
  wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
31329
- wrapper[kListener] = handler14;
31329
+ wrapper[kListener] = handler15;
31330
31330
  if (options.once) {
31331
31331
  this.once(type, wrapper);
31332
31332
  } else {
31333
31333
  this.on(type, wrapper);
31334
31334
  }
31335
31335
  },
31336
- removeEventListener(type, handler14) {
31336
+ removeEventListener(type, handler15) {
31337
31337
  for (const listener of this.listeners(type)) {
31338
- if (listener[kListener] === handler14 && !listener[kForOnEventAttribute]) {
31338
+ if (listener[kListener] === handler15 && !listener[kForOnEventAttribute]) {
31339
31339
  this.removeListener(type, listener);
31340
31340
  break;
31341
31341
  }
@@ -31861,16 +31861,16 @@ var require_websocket = __commonJS((exports, module) => {
31861
31861
  }
31862
31862
  return null;
31863
31863
  },
31864
- set(handler14) {
31864
+ set(handler15) {
31865
31865
  for (const listener of this.listeners(method)) {
31866
31866
  if (listener[kForOnEventAttribute]) {
31867
31867
  this.removeListener(method, listener);
31868
31868
  break;
31869
31869
  }
31870
31870
  }
31871
- if (typeof handler14 !== "function")
31871
+ if (typeof handler15 !== "function")
31872
31872
  return;
31873
- this.addEventListener(method, handler14, {
31873
+ this.addEventListener(method, handler15, {
31874
31874
  [kForOnEventAttribute]: true
31875
31875
  });
31876
31876
  }
@@ -32730,7 +32730,7 @@ var require_websocket_server = __commonJS((exports, module) => {
32730
32730
  });
32731
32731
 
32732
32732
  // src/index.ts
32733
- var import_config2 = __toESM(require_config(), 1);
32733
+ var import_config3 = __toESM(require_config(), 1);
32734
32734
 
32735
32735
  // ../../node_modules/commander/esm.mjs
32736
32736
  var import__ = __toESM(require_commander(), 1);
@@ -32748,7 +32748,7 @@ var {
32748
32748
  Help
32749
32749
  } = import__.default;
32750
32750
  // package.json
32751
- var version = "0.8.11";
32751
+ var version = "0.8.13";
32752
32752
 
32753
32753
  // src/runner.ts
32754
32754
  import { execSync } from "node:child_process";
@@ -32762,8 +32762,10 @@ import { join as join2 } from "node:path";
32762
32762
  // ../core/src/AiService/AiServiceBase.ts
32763
32763
  class AiServiceBase {
32764
32764
  usageMeter;
32765
- constructor(usageMeter) {
32766
- this.usageMeter = usageMeter;
32765
+ options;
32766
+ constructor(options) {
32767
+ this.options = options;
32768
+ this.usageMeter = options.usageMeter;
32767
32769
  }
32768
32770
  async* send(systemPrompt, messages) {
32769
32771
  this.usageMeter.checkLimit();
@@ -36249,7 +36251,7 @@ class AnthropicService extends AiServiceBase {
36249
36251
  #client;
36250
36252
  model;
36251
36253
  constructor(options) {
36252
- super(options.usageMeter);
36254
+ super(options);
36253
36255
  this.#options = options;
36254
36256
  this.#client = new Anthropic({
36255
36257
  apiKey: options.apiKey,
@@ -41676,7 +41678,7 @@ class DeepSeekService extends AiServiceBase {
41676
41678
  #client;
41677
41679
  model;
41678
41680
  constructor(options) {
41679
- super(options.usageMeter);
41681
+ super(options);
41680
41682
  this.#client = new openai_default({
41681
41683
  baseURL: "https://api.deepseek.com/v1",
41682
41684
  apiKey: options.apiKey
@@ -41733,7 +41735,7 @@ class OllamaService extends AiServiceBase {
41733
41735
  #client;
41734
41736
  model;
41735
41737
  constructor(options) {
41736
- super(options.usageMeter);
41738
+ super(options);
41737
41739
  this.#client = new openai_default({
41738
41740
  baseURL: `${options.baseUrl || "http://localhost:11434"}/v1`,
41739
41741
  apiKey: "ollama"
@@ -41775,7 +41777,7 @@ class OpenRouterService extends AiServiceBase {
41775
41777
  #modelProviderInfo;
41776
41778
  model;
41777
41779
  constructor(options) {
41778
- super(options.usageMeter);
41780
+ super(options);
41779
41781
  if (!options.model) {
41780
41782
  throw new Error("OpenRouter requires a model");
41781
41783
  }
@@ -42048,73 +42050,98 @@ __export(exports_allTools, {
42048
42050
  writeToFile: () => writeToFile_default,
42049
42051
  updateKnowledge: () => updateKnowledge_default,
42050
42052
  searchFiles: () => searchFiles_default,
42051
- replaceInFile: () => replaceInFile_default,
42052
42053
  renameFile: () => renameFile_default,
42053
42054
  removeFile: () => removeFile_default,
42054
42055
  readFile: () => readFile_default,
42055
42056
  listFiles: () => listFiles_default,
42056
42057
  handOver: () => handOver_default,
42057
42058
  executeCommand: () => executeCommand_default,
42059
+ editFile: () => editFile_default,
42058
42060
  delegate: () => delegate_default,
42059
42061
  attemptCompletion: () => attemptCompletion_default,
42060
42062
  askFollowupQuestion: () => askFollowupQuestion_default
42061
42063
  });
42062
42064
 
42063
- // ../core/src/tools/utils/replaceInFile.ts
42064
- var replaceInFile = async (fileContent, diff) => {
42065
- const blockPattern = /<<<<<+ SEARCH\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
42066
- const blocks = [];
42067
- for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
42068
- blocks.push({ search: match[1], replace: match[2] });
42065
+ // ../core/src/tools/utils/editFile.ts
42066
+ var START_OF_FILE = "<<<START_OF_FILE>>>";
42067
+ var END_OF_FILE = "<<<END_OF_FILE>>>";
42068
+ var editFile = async (fileContent, operations) => {
42069
+ if (!operations || operations.length === 0) {
42070
+ throw new Error("At least one edit operation is required");
42069
42071
  }
42070
- if (blocks.length === 0) {
42071
- throw new Error("No valid diff blocks found.");
42072
+ const originalLines = fileContent.split(`
42073
+ `);
42074
+ let updatedContent = fileContent;
42075
+ for (const operation of operations) {
42076
+ updatedContent = await applyEditOperation(updatedContent, operation, originalLines);
42072
42077
  }
42073
- const findAndReplace = (content, search, replace) => {
42074
- let index = content.indexOf(search);
42075
- if (index !== -1) {
42076
- return content.slice(0, index) + replace + content.slice(index + search.length);
42078
+ return updatedContent;
42079
+ };
42080
+ async function applyEditOperation(fileContent, operation, originalLines) {
42081
+ const { before_text, after_text, new_text, before_text_line_start, after_text_line_start } = operation;
42082
+ if (before_text === START_OF_FILE && after_text === END_OF_FILE) {
42083
+ return new_text;
42084
+ }
42085
+ if (before_text === START_OF_FILE) {
42086
+ if (!after_text) {
42087
+ return new_text + fileContent;
42077
42088
  }
42078
- const trimmedSearch = search.trim();
42079
- const trimmedContent = content.trim();
42080
- const offset = content.indexOf(trimmedContent);
42081
- index = trimmedContent.indexOf(trimmedSearch);
42082
- if (index !== -1) {
42083
- const absoluteIndex = offset + index;
42084
- return content.slice(0, absoluteIndex) + replace + content.slice(absoluteIndex + trimmedSearch.length);
42089
+ const afterIndex = findTextWithHint(fileContent, after_text, after_text_line_start, originalLines);
42090
+ return new_text + fileContent.slice(afterIndex);
42091
+ }
42092
+ if (after_text === END_OF_FILE) {
42093
+ if (!before_text) {
42094
+ return fileContent + new_text;
42085
42095
  }
42086
- const normalizedSearch = trimmedSearch.replace(/\s+/g, " ");
42087
- const normalizedContent = trimmedContent.replace(/\s+/g, " ");
42088
- index = normalizedContent.indexOf(normalizedSearch);
42089
- if (index !== -1) {
42090
- let runningIndex = 0;
42091
- let actualPos = offset;
42092
- for (const segment of trimmedSearch.replace(/\s+/g, " ").split(" ")) {
42093
- const segIndex = content.indexOf(segment, actualPos);
42094
- if (segIndex === -1) {
42095
- break;
42096
- }
42097
- if (runningIndex === 0) {
42098
- actualPos = segIndex;
42099
- } else {
42100
- actualPos = segIndex + segment.length;
42101
- }
42102
- runningIndex++;
42096
+ const beforeIndex = findTextWithHint(fileContent, before_text, before_text_line_start, originalLines);
42097
+ const beforeEndIndex = beforeIndex + before_text.length;
42098
+ return fileContent.slice(0, beforeEndIndex) + new_text;
42099
+ }
42100
+ if (before_text && after_text) {
42101
+ const beforeIndex = findTextWithHint(fileContent, before_text, before_text_line_start, originalLines);
42102
+ const beforeEndIndex = beforeIndex + before_text.length;
42103
+ const afterIndex = findTextWithHint(fileContent, after_text, after_text_line_start, originalLines, beforeEndIndex);
42104
+ return fileContent.slice(0, beforeEndIndex) + new_text + fileContent.slice(afterIndex);
42105
+ }
42106
+ if (before_text) {
42107
+ const beforeIndex = findTextWithHint(fileContent, before_text, before_text_line_start, originalLines);
42108
+ const beforeEndIndex = beforeIndex + before_text.length;
42109
+ return fileContent.slice(0, beforeEndIndex) + new_text + fileContent.slice(beforeEndIndex);
42110
+ }
42111
+ if (after_text) {
42112
+ const afterIndex = findTextWithHint(fileContent, after_text, after_text_line_start, originalLines);
42113
+ return fileContent.slice(0, afterIndex) + new_text + fileContent.slice(afterIndex);
42114
+ }
42115
+ throw new Error("Either before_text or after_text must be specified");
42116
+ }
42117
+ function findTextWithHint(content, searchText, lineHint, originalLines, startIndex = 0) {
42118
+ if (lineHint && lineHint > 0 && lineHint <= originalLines.length) {
42119
+ const hintIndex = getLineStartIndex(originalLines, lineHint - 1);
42120
+ const searchRadius = 5;
42121
+ const windowStart = Math.max(0, hintIndex - searchRadius * 50);
42122
+ const windowEnd = Math.min(content.length, hintIndex + searchRadius * 50);
42123
+ const windowContent = content.slice(windowStart, windowEnd);
42124
+ const relativeIndex = windowContent.indexOf(searchText);
42125
+ if (relativeIndex !== -1) {
42126
+ const absoluteIndex = windowStart + relativeIndex;
42127
+ if (absoluteIndex >= startIndex) {
42128
+ return absoluteIndex;
42103
42129
  }
42104
- const strippedSearch = trimmedSearch.replace(/\s+/g, "");
42105
- const endPos = actualPos;
42106
- const startPos = endPos - strippedSearch.length;
42107
- return content.slice(0, startPos) + replace + content.slice(endPos);
42108
42130
  }
42109
- throw new Error(`Could not find the following text in file:
42110
- ${search}`);
42111
- };
42112
- let updatedFile = fileContent;
42113
- for (const { search, replace } of blocks) {
42114
- updatedFile = findAndReplace(updatedFile, search, replace);
42115
42131
  }
42116
- return updatedFile;
42117
- };
42132
+ const index = content.indexOf(searchText, startIndex);
42133
+ if (index === -1) {
42134
+ throw new Error(`Could not find text: ${searchText}`);
42135
+ }
42136
+ return index;
42137
+ }
42138
+ function getLineStartIndex(lines, lineIndex) {
42139
+ let index = 0;
42140
+ for (let i2 = 0;i2 < lineIndex && i2 < lines.length; i2++) {
42141
+ index += lines[i2].length + 1;
42142
+ }
42143
+ return index;
42144
+ }
42118
42145
  // ../core/src/tools/utils/getArg.ts
42119
42146
  var getString = (args, name, defaultValue) => {
42120
42147
  if (typeof args !== "object" || Array.isArray(args)) {
@@ -42206,6 +42233,61 @@ var getArray = (args, name, defaultValue) => {
42206
42233
  }
42207
42234
  return [ret];
42208
42235
  };
42236
+ // ../core/src/tools/utils/replaceInFile.ts
42237
+ var replaceInFile = async (fileContent, diff) => {
42238
+ const blockPattern = /<<<<<+ SEARCH\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
42239
+ const blocks = [];
42240
+ for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
42241
+ blocks.push({ search: match[1], replace: match[2] });
42242
+ }
42243
+ if (blocks.length === 0) {
42244
+ throw new Error("No valid diff blocks found.");
42245
+ }
42246
+ const findAndReplace = (content, search, replace) => {
42247
+ let index = content.indexOf(search);
42248
+ if (index !== -1) {
42249
+ return content.slice(0, index) + replace + content.slice(index + search.length);
42250
+ }
42251
+ const trimmedSearch = search.trim();
42252
+ const trimmedContent = content.trim();
42253
+ const offset = content.indexOf(trimmedContent);
42254
+ index = trimmedContent.indexOf(trimmedSearch);
42255
+ if (index !== -1) {
42256
+ const absoluteIndex = offset + index;
42257
+ return content.slice(0, absoluteIndex) + replace + content.slice(absoluteIndex + trimmedSearch.length);
42258
+ }
42259
+ const normalizedSearch = trimmedSearch.replace(/\s+/g, " ");
42260
+ const normalizedContent = trimmedContent.replace(/\s+/g, " ");
42261
+ index = normalizedContent.indexOf(normalizedSearch);
42262
+ if (index !== -1) {
42263
+ let runningIndex = 0;
42264
+ let actualPos = offset;
42265
+ for (const segment of trimmedSearch.replace(/\s+/g, " ").split(" ")) {
42266
+ const segIndex = content.indexOf(segment, actualPos);
42267
+ if (segIndex === -1) {
42268
+ break;
42269
+ }
42270
+ if (runningIndex === 0) {
42271
+ actualPos = segIndex;
42272
+ } else {
42273
+ actualPos = segIndex + segment.length;
42274
+ }
42275
+ runningIndex++;
42276
+ }
42277
+ const strippedSearch = trimmedSearch.replace(/\s+/g, "");
42278
+ const endPos = actualPos;
42279
+ const startPos = endPos - strippedSearch.length;
42280
+ return content.slice(0, startPos) + replace + content.slice(endPos);
42281
+ }
42282
+ throw new Error(`Could not find the following text in file:
42283
+ ${search}`);
42284
+ };
42285
+ let updatedFile = fileContent;
42286
+ for (const { search, replace } of blocks) {
42287
+ updatedFile = findAndReplace(updatedFile, search, replace);
42288
+ }
42289
+ return updatedFile;
42290
+ };
42209
42291
  // ../core/src/tools/askFollowupQuestion.ts
42210
42292
  var toolInfo = {
42211
42293
  name: "ask_followup_question",
@@ -42449,11 +42531,11 @@ var delegate_default = {
42449
42531
  // ../core/src/tools/executeCommand.ts
42450
42532
  var toolInfo4 = {
42451
42533
  name: "execute_command",
42452
- description: "Run a single CLI command. The command is always executed in the project-root working directory (regardless of earlier commands). Prefer one-off shell commands over wrapper scripts for flexibility. After an `execute_command` call, no other tool calls are allowed in the same assistant response.",
42534
+ description: "Run a single CLI command. The command is always executed in the project-root working directory (regardless of earlier commands). Prefer one-off shell commands over wrapper scripts for flexibility. **IMPORTANT**: After an `execute_command` call, you MUST stop and NOT allowed to make further tool calls in the same message.",
42453
42535
  parameters: [
42454
42536
  {
42455
42537
  name: "command",
42456
- description: "The exact command to run (valid for the current OS). It must be correctly formatted and free of harmful instructions.",
42538
+ description: "The exact command to run (valid for the current OS). It must be correctly formatted and free of harmful instructions.",
42457
42539
  required: true,
42458
42540
  usageValue: "your-command-here"
42459
42541
  },
@@ -42652,125 +42734,8 @@ var readFile_default = {
42652
42734
  handler: handler6,
42653
42735
  isAvailable: isAvailable6
42654
42736
  };
42655
- // ../core/src/tools/replaceInFile.ts
42656
- var toolInfo7 = {
42657
- name: "replace_in_file",
42658
- 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.",
42659
- parameters: [
42660
- {
42661
- name: "path",
42662
- description: "The path of the file to modify",
42663
- required: true,
42664
- usageValue: "File path here"
42665
- },
42666
- {
42667
- name: "diff",
42668
- description: `One or more SEARCH/REPLACE blocks following this exact format:
42669
- \`\`\`
42670
- <<<<<<< SEARCH
42671
- [exact content to find]
42672
- =======
42673
- [new content to replace with]
42674
- >>>>>>> REPLACE
42675
- \`\`\`
42676
- Critical rules:
42677
- 1. SEARCH content must match the associated file section to find EXACTLY:
42678
- * Match character-for-character including whitespace, indentation, line endings
42679
- * Include all comments, docstrings, etc.
42680
- 2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
42681
- * Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
42682
- * Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
42683
- * When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
42684
- 3. Keep SEARCH/REPLACE blocks concise:
42685
- * Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
42686
- * Include just the changing lines, and a few surrounding lines if needed for uniqueness.
42687
- * Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
42688
- * Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
42689
- 4. Special operations:
42690
- * To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
42691
- * To delete code: Use empty REPLACE section`,
42692
- required: true,
42693
- usageValue: "Search and replace blocks here"
42694
- }
42695
- ],
42696
- examples: [
42697
- {
42698
- description: "Request to replace sections of content in a file",
42699
- parameters: [
42700
- {
42701
- name: "path",
42702
- value: "src/main.js"
42703
- },
42704
- {
42705
- name: "diff",
42706
- value: `
42707
- <<<<<<< SEARCH
42708
- import React from 'react';
42709
- =======
42710
- import React, { useState } from 'react';
42711
- >>>>>>> REPLACE
42712
-
42713
- <<<<<<< SEARCH
42714
- function handleSubmit() {
42715
- saveData();
42716
- setLoading(false);
42717
- }
42718
-
42719
- =======
42720
- >>>>>>> REPLACE
42721
-
42722
- <<<<<<< SEARCH
42723
- return (
42724
- <div>
42725
- =======
42726
- function handleSubmit() {
42727
- saveData();
42728
- setLoading(false);
42729
- }
42730
-
42731
- return (
42732
- <div>
42733
- >>>>>>> REPLACE
42734
- `
42735
- }
42736
- ]
42737
- }
42738
- ],
42739
- permissionLevel: 2 /* Write */
42740
- };
42741
- var handler7 = async (provider, args) => {
42742
- if (!provider.readFile || !provider.writeFile) {
42743
- return {
42744
- type: "Error" /* Error */,
42745
- message: "Not possible to replace in file. Abort."
42746
- };
42747
- }
42748
- const path = getString(args, "path");
42749
- const diff = getString(args, "diff");
42750
- const fileContent = await provider.readFile(path);
42751
- if (fileContent == null) {
42752
- return {
42753
- type: "Error" /* Error */,
42754
- message: `<error><replace_in_file_path>${path}</replace_in_file_path><error_message>File not found</error_message></error>`
42755
- };
42756
- }
42757
- const result = await replaceInFile(fileContent, diff);
42758
- await provider.writeFile(path, result);
42759
- return {
42760
- type: "Reply" /* Reply */,
42761
- message: `<replace_in_file_path>${path}</replace_in_file_path>`
42762
- };
42763
- };
42764
- var isAvailable7 = (provider) => {
42765
- return !!provider.readFile && !!provider.writeFile;
42766
- };
42767
- var replaceInFile_default = {
42768
- ...toolInfo7,
42769
- handler: handler7,
42770
- isAvailable: isAvailable7
42771
- };
42772
42737
  // ../core/src/tools/searchFiles.ts
42773
- var toolInfo8 = {
42738
+ var toolInfo7 = {
42774
42739
  name: "search_files",
42775
42740
  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.",
42776
42741
  parameters: [
@@ -42814,7 +42779,7 @@ var toolInfo8 = {
42814
42779
  ],
42815
42780
  permissionLevel: 1 /* Read */
42816
42781
  };
42817
- var handler8 = async (provider, args) => {
42782
+ var handler7 = async (provider, args) => {
42818
42783
  if (!provider.searchFiles) {
42819
42784
  return {
42820
42785
  type: "Error" /* Error */,
@@ -42837,18 +42802,18 @@ ${files.join(`
42837
42802
  `
42838
42803
  };
42839
42804
  };
42840
- var isAvailable8 = (provider) => {
42805
+ var isAvailable7 = (provider) => {
42841
42806
  return !!provider.searchFiles;
42842
42807
  };
42843
42808
  var searchFiles_default = {
42844
- ...toolInfo8,
42845
- handler: handler8,
42846
- isAvailable: isAvailable8
42809
+ ...toolInfo7,
42810
+ handler: handler7,
42811
+ isAvailable: isAvailable7
42847
42812
  };
42848
42813
  // ../core/src/tools/updateKnowledge.ts
42849
42814
  var import_yaml = __toESM(require_dist(), 1);
42850
42815
  import { join } from "node:path";
42851
- var toolInfo9 = {
42816
+ var toolInfo8 = {
42852
42817
  name: "update_knowledge",
42853
42818
  description: "Update knowledge in a knowledge.ai.yml file with smart merging capabilities. This tool lets you add, update, or remove information using path-based updates and special directives.",
42854
42819
  parameters: [
@@ -43025,7 +42990,7 @@ function deepMerge(target, source) {
43025
42990
  }
43026
42991
  return output;
43027
42992
  }
43028
- var handler9 = async (provider, args) => {
42993
+ var handler8 = async (provider, args) => {
43029
42994
  if (!provider.readFile || !provider.writeFile) {
43030
42995
  return {
43031
42996
  type: "Error" /* Error */,
@@ -43097,16 +43062,16 @@ var handler9 = async (provider, args) => {
43097
43062
  };
43098
43063
  }
43099
43064
  };
43100
- var isAvailable9 = (provider) => {
43065
+ var isAvailable8 = (provider) => {
43101
43066
  return !!provider.readFile && !!provider.writeFile;
43102
43067
  };
43103
43068
  var updateKnowledge_default = {
43104
- ...toolInfo9,
43105
- handler: handler9,
43106
- isAvailable: isAvailable9
43069
+ ...toolInfo8,
43070
+ handler: handler8,
43071
+ isAvailable: isAvailable8
43107
43072
  };
43108
43073
  // ../core/src/tools/writeToFile.ts
43109
- var toolInfo10 = {
43074
+ var toolInfo9 = {
43110
43075
  name: "write_to_file",
43111
43076
  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. Ensure that the output content does not include incorrect escaped character patterns such as `&lt;` and `&gt;`.",
43112
43077
  parameters: [
@@ -43151,7 +43116,7 @@ export default App;
43151
43116
  ],
43152
43117
  permissionLevel: 2 /* Write */
43153
43118
  };
43154
- var handler10 = async (provider, args) => {
43119
+ var handler9 = async (provider, args) => {
43155
43120
  if (!provider.writeFile) {
43156
43121
  return {
43157
43122
  type: "Error" /* Error */,
@@ -43166,16 +43131,16 @@ var handler10 = async (provider, args) => {
43166
43131
  message: `<write_to_file_path>${path}</write_to_file_path><status>Success</status>`
43167
43132
  };
43168
43133
  };
43169
- var isAvailable10 = (provider) => {
43134
+ var isAvailable9 = (provider) => {
43170
43135
  return !!provider.writeFile;
43171
43136
  };
43172
43137
  var writeToFile_default = {
43173
- ...toolInfo10,
43174
- handler: handler10,
43175
- isAvailable: isAvailable10
43138
+ ...toolInfo9,
43139
+ handler: handler9,
43140
+ isAvailable: isAvailable9
43176
43141
  };
43177
43142
  // ../core/src/tools/handOver.ts
43178
- var toolInfo11 = {
43143
+ var toolInfo10 = {
43179
43144
  name: "hand_over",
43180
43145
  description: "Hand over the current task to another agent to complete. This tool MUST NOT to be used with any other tool.",
43181
43146
  parameters: [
@@ -43229,7 +43194,7 @@ var toolInfo11 = {
43229
43194
  ],
43230
43195
  permissionLevel: 0 /* None */
43231
43196
  };
43232
- var handler11 = async (_provider, args) => {
43197
+ var handler10 = async (_provider, args) => {
43233
43198
  const agentName = getString(args, "agent_name");
43234
43199
  const task = getString(args, "task");
43235
43200
  const context = getString(args, "context", undefined);
@@ -43242,16 +43207,16 @@ var handler11 = async (_provider, args) => {
43242
43207
  files
43243
43208
  };
43244
43209
  };
43245
- var isAvailable11 = (_provider) => {
43210
+ var isAvailable10 = (_provider) => {
43246
43211
  return true;
43247
43212
  };
43248
43213
  var handOver_default = {
43249
- ...toolInfo11,
43250
- handler: handler11,
43251
- isAvailable: isAvailable11
43214
+ ...toolInfo10,
43215
+ handler: handler10,
43216
+ isAvailable: isAvailable10
43252
43217
  };
43253
43218
  // ../core/src/tools/removeFile.ts
43254
- var toolInfo12 = {
43219
+ var toolInfo11 = {
43255
43220
  name: "remove_file",
43256
43221
  description: "Request to remove a file at the specified path.",
43257
43222
  parameters: [
@@ -43275,7 +43240,7 @@ var toolInfo12 = {
43275
43240
  ],
43276
43241
  permissionLevel: 2 /* Write */
43277
43242
  };
43278
- var handler12 = async (provider, args) => {
43243
+ var handler11 = async (provider, args) => {
43279
43244
  if (!provider.removeFile) {
43280
43245
  return {
43281
43246
  type: "Error" /* Error */,
@@ -43289,27 +43254,27 @@ var handler12 = async (provider, args) => {
43289
43254
  message: `<remove_file_path>${path}</remove_file_path><status>Success</status>`
43290
43255
  };
43291
43256
  };
43292
- var isAvailable12 = (provider) => {
43257
+ var isAvailable11 = (provider) => {
43293
43258
  return !!provider.removeFile;
43294
43259
  };
43295
43260
  var removeFile_default = {
43296
- ...toolInfo12,
43297
- handler: handler12,
43298
- isAvailable: isAvailable12
43261
+ ...toolInfo11,
43262
+ handler: handler11,
43263
+ isAvailable: isAvailable11
43299
43264
  };
43300
43265
  // ../core/src/tools/renameFile.ts
43301
- var toolInfo13 = {
43266
+ var toolInfo12 = {
43302
43267
  name: "rename_file",
43303
43268
  description: "Request to rename a file from source path to target path.",
43304
43269
  parameters: [
43305
43270
  {
43306
- name: "sourcePath",
43271
+ name: "source_path",
43307
43272
  description: "The current path of the file",
43308
43273
  required: true,
43309
43274
  usageValue: "Source file path here"
43310
43275
  },
43311
43276
  {
43312
- name: "targetPath",
43277
+ name: "target_path",
43313
43278
  description: "The new path for the file",
43314
43279
  required: true,
43315
43280
  usageValue: "Target file path here"
@@ -43320,11 +43285,11 @@ var toolInfo13 = {
43320
43285
  description: "Request to rename a file",
43321
43286
  parameters: [
43322
43287
  {
43323
- name: "sourcePath",
43288
+ name: "source_path",
43324
43289
  value: "src/old-name.js"
43325
43290
  },
43326
43291
  {
43327
- name: "targetPath",
43292
+ name: "target_path",
43328
43293
  value: "src/new-name.js"
43329
43294
  }
43330
43295
  ]
@@ -43332,29 +43297,308 @@ var toolInfo13 = {
43332
43297
  ],
43333
43298
  permissionLevel: 2 /* Write */
43334
43299
  };
43335
- var handler13 = async (provider, args) => {
43300
+ var handler12 = async (provider, args) => {
43336
43301
  if (!provider.renameFile) {
43337
43302
  return {
43338
43303
  type: "Error" /* Error */,
43339
43304
  message: "Not possible to rename file. Abort."
43340
43305
  };
43341
43306
  }
43342
- const sourcePath = getString(args, "sourcePath");
43343
- const targetPath = getString(args, "targetPath");
43307
+ const sourcePath = getString(args, "source_path");
43308
+ const targetPath = getString(args, "target_path");
43344
43309
  await provider.renameFile(sourcePath, targetPath);
43345
43310
  return {
43346
43311
  type: "Reply" /* Reply */,
43347
43312
  message: `<rename_file_path>${targetPath}</rename_file_path><status>Success</status>`
43348
43313
  };
43349
43314
  };
43350
- var isAvailable13 = (provider) => {
43315
+ var isAvailable12 = (provider) => {
43351
43316
  return !!provider.renameFile;
43352
43317
  };
43353
43318
  var renameFile_default = {
43319
+ ...toolInfo12,
43320
+ handler: handler12,
43321
+ isAvailable: isAvailable12
43322
+ };
43323
+ // ../core/src/tools/editFile.ts
43324
+ var toolInfo13 = {
43325
+ name: "edit_file",
43326
+ description: "Request to edit file contents using before/after text anchors with flexible operations. Supports multiple edit operations in a single call.",
43327
+ parameters: [
43328
+ {
43329
+ name: "path",
43330
+ description: "The path of the file to edit",
43331
+ required: true,
43332
+ usageValue: "File path here"
43333
+ },
43334
+ {
43335
+ name: "operations",
43336
+ description: "Edit operation with before_text, after_text, new_text, and optional line range hints",
43337
+ required: true,
43338
+ allowMultiple: true,
43339
+ children: [
43340
+ {
43341
+ name: "before_text",
43342
+ description: `Text to find as the start anchor (use ${START_OF_FILE} for file start)`,
43343
+ required: false,
43344
+ usageValue: "Text before the edit location"
43345
+ },
43346
+ {
43347
+ name: "after_text",
43348
+ description: `Text to find as the end anchor (use ${END_OF_FILE} for file end)`,
43349
+ required: false,
43350
+ usageValue: "Text after the edit location"
43351
+ },
43352
+ {
43353
+ name: "new_text",
43354
+ description: "Text to replace the content between before_text and after_text",
43355
+ required: true,
43356
+ usageValue: "New text content"
43357
+ },
43358
+ {
43359
+ name: "before_text_line_start",
43360
+ description: "Optional line number hint for before_text location (1-based)",
43361
+ required: false,
43362
+ usageValue: "10"
43363
+ },
43364
+ {
43365
+ name: "after_text_line_start",
43366
+ description: "Optional line number hint for after_text location (1-based)",
43367
+ required: false,
43368
+ usageValue: "20"
43369
+ }
43370
+ ],
43371
+ usageValue: "operations here"
43372
+ }
43373
+ ],
43374
+ examples: [
43375
+ {
43376
+ description: "Replace content between two text anchors",
43377
+ parameters: [
43378
+ {
43379
+ name: "path",
43380
+ value: "src/main.ts"
43381
+ },
43382
+ {
43383
+ name: "operations",
43384
+ value: {
43385
+ before_text: "function oldFunction() {",
43386
+ after_text: "}",
43387
+ new_text: `
43388
+ return "new implementation";
43389
+ `
43390
+ }
43391
+ }
43392
+ ]
43393
+ },
43394
+ {
43395
+ description: "Insert at start of file",
43396
+ parameters: [
43397
+ {
43398
+ name: "path",
43399
+ value: "src/header.ts"
43400
+ },
43401
+ {
43402
+ name: "operations",
43403
+ value: {
43404
+ before_text: START_OF_FILE,
43405
+ after_text: "export",
43406
+ new_text: `// File header comment
43407
+ `
43408
+ }
43409
+ }
43410
+ ]
43411
+ },
43412
+ {
43413
+ description: "Multiple operations in one call",
43414
+ parameters: [
43415
+ {
43416
+ name: "path",
43417
+ value: "src/utils.ts"
43418
+ },
43419
+ {
43420
+ name: "operations",
43421
+ value: [
43422
+ {
43423
+ before_text: "import React",
43424
+ after_text: 'from "react"',
43425
+ new_text: ", { useState }"
43426
+ },
43427
+ {
43428
+ before_text: "function Component() {",
43429
+ after_text: "return (",
43430
+ new_text: `
43431
+ const [state, setState] = useState(false);
43432
+ `
43433
+ }
43434
+ ]
43435
+ }
43436
+ ]
43437
+ }
43438
+ ],
43439
+ permissionLevel: 2 /* Write */
43440
+ };
43441
+ var handler13 = async (provider, args) => {
43442
+ if (!provider.readFile || !provider.writeFile) {
43443
+ return {
43444
+ type: "Error" /* Error */,
43445
+ message: "Not possible to edit file. Abort."
43446
+ };
43447
+ }
43448
+ const path = getString(args, "path");
43449
+ const operations = getArray(args, "operations");
43450
+ if (!operations || operations.length === 0) {
43451
+ return {
43452
+ type: "Error" /* Error */,
43453
+ message: `<error><edit_file_path>${path}</edit_file_path><error_message>At least one edit operation is required</error_message></error>`
43454
+ };
43455
+ }
43456
+ const fileContent = await provider.readFile(path);
43457
+ if (fileContent == null) {
43458
+ return {
43459
+ type: "Error" /* Error */,
43460
+ message: `<error><edit_file_path>${path}</edit_file_path><error_message>File not found</error_message></error>`
43461
+ };
43462
+ }
43463
+ try {
43464
+ const result = await editFile(fileContent, operations);
43465
+ await provider.writeFile(path, result);
43466
+ return {
43467
+ type: "Reply" /* Reply */,
43468
+ message: `<edit_file_path>${path}</edit_file_path>`
43469
+ };
43470
+ } catch (error) {
43471
+ return {
43472
+ type: "Error" /* Error */,
43473
+ message: `<error><edit_file_path>${path}</edit_file_path><error_message>${error instanceof Error ? error.message : String(error)}</error_message></error>`
43474
+ };
43475
+ }
43476
+ };
43477
+ var isAvailable13 = (provider) => {
43478
+ return !!provider.readFile && !!provider.writeFile;
43479
+ };
43480
+ var editFile_default = {
43354
43481
  ...toolInfo13,
43355
43482
  handler: handler13,
43356
43483
  isAvailable: isAvailable13
43357
43484
  };
43485
+ // ../core/src/tools/replaceInFile.ts
43486
+ var toolInfo14 = {
43487
+ name: "replace_in_file",
43488
+ 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.",
43489
+ parameters: [
43490
+ {
43491
+ name: "path",
43492
+ description: "The path of the file to modify",
43493
+ required: true,
43494
+ usageValue: "File path here"
43495
+ },
43496
+ {
43497
+ name: "diff",
43498
+ description: `One or more SEARCH/REPLACE blocks following this exact format:
43499
+ \`\`\`
43500
+ <<<<<<< SEARCH
43501
+ [exact content to find]
43502
+ =======
43503
+ [new content to replace with]
43504
+ >>>>>>> REPLACE
43505
+ \`\`\`
43506
+ Critical rules:
43507
+ 1. SEARCH content must match the associated file section to find EXACTLY:
43508
+ * Match character-for-character including whitespace, indentation, line endings
43509
+ * Include all comments, docstrings, etc.
43510
+ 2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
43511
+ * Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
43512
+ * Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
43513
+ * When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
43514
+ 3. Keep SEARCH/REPLACE blocks concise:
43515
+ * Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
43516
+ * Include just the changing lines, and a few surrounding lines if needed for uniqueness.
43517
+ * Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
43518
+ * Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
43519
+ 4. Special operations:
43520
+ * To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
43521
+ * To delete code: Use empty REPLACE section`,
43522
+ required: true,
43523
+ usageValue: "Search and replace blocks here"
43524
+ }
43525
+ ],
43526
+ examples: [
43527
+ {
43528
+ description: "Request to replace sections of content in a file",
43529
+ parameters: [
43530
+ {
43531
+ name: "path",
43532
+ value: "src/main.js"
43533
+ },
43534
+ {
43535
+ name: "diff",
43536
+ value: `
43537
+ <<<<<<< SEARCH
43538
+ import React from 'react';
43539
+ =======
43540
+ import React, { useState } from 'react';
43541
+ >>>>>>> REPLACE
43542
+
43543
+ <<<<<<< SEARCH
43544
+ function handleSubmit() {
43545
+ saveData();
43546
+ setLoading(false);
43547
+ }
43548
+
43549
+ =======
43550
+ >>>>>>> REPLACE
43551
+
43552
+ <<<<<<< SEARCH
43553
+ return (
43554
+ <div>
43555
+ =======
43556
+ function handleSubmit() {
43557
+ saveData();
43558
+ setLoading(false);
43559
+ }
43560
+
43561
+ return (
43562
+ <div>
43563
+ >>>>>>> REPLACE
43564
+ `
43565
+ }
43566
+ ]
43567
+ }
43568
+ ],
43569
+ permissionLevel: 2 /* Write */
43570
+ };
43571
+ var handler14 = async (provider, args) => {
43572
+ if (!provider.readFile || !provider.writeFile) {
43573
+ return {
43574
+ type: "Error" /* Error */,
43575
+ message: "Not possible to replace in file. Abort."
43576
+ };
43577
+ }
43578
+ const path = getString(args, "path");
43579
+ const diff = getString(args, "diff");
43580
+ const fileContent = await provider.readFile(path);
43581
+ if (fileContent == null) {
43582
+ return {
43583
+ type: "Error" /* Error */,
43584
+ message: `<error><replace_in_file_path>${path}</replace_in_file_path><error_message>File not found</error_message></error>`
43585
+ };
43586
+ }
43587
+ const result = await replaceInFile(fileContent, diff);
43588
+ await provider.writeFile(path, result);
43589
+ return {
43590
+ type: "Reply" /* Reply */,
43591
+ message: `<replace_in_file_path>${path}</replace_in_file_path>`
43592
+ };
43593
+ };
43594
+ var isAvailable14 = (provider) => {
43595
+ return !!provider.readFile && !!provider.writeFile;
43596
+ };
43597
+ var replaceInFile_default = {
43598
+ ...toolInfo14,
43599
+ handler: handler14,
43600
+ isAvailable: isAvailable14
43601
+ };
43358
43602
  // ../core/src/getAvailableTools.ts
43359
43603
  var getAvailableTools = ({
43360
43604
  provider: provider2,
@@ -43567,7 +43811,7 @@ var toolUsePrompt = (tools, toolNamePrefix) => {
43567
43811
 
43568
43812
  TOOL USE
43569
43813
 
43570
- 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.
43814
+ You have access to a set of tools that are executed upon the user's approval. You can use up to 5 tool calls per message, and will receive the results of those tool uses 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.
43571
43815
 
43572
43816
  # Tool Use Formatting
43573
43817
 
@@ -43633,18 +43877,16 @@ ${tools.map((tool) => {
43633
43877
 
43634
43878
  1. **Outline Your Thought Process**
43635
43879
  - Before using a tool, wrap your reasoning inside \`<thinking>\` tags. Be concise—just enough to clarify your plan and the rationale behind selecting a specific tool.
43636
-
43637
43880
  2. **Wait for Feedback**
43638
43881
  - After using a tool, wait for the user's response indicating success/failure or any output logs. Do not assume the result of a tool without explicit confirmation.
43639
-
43640
43882
  3. **Error Handling**
43641
43883
  - If a tool fails or produces an unexpected result, analyze the error, decide on an alternative approach or tool, and proceed carefully.
43642
-
43643
43884
  4. **Avoid Repetition**
43644
43885
  - Do not quote or repeat previous commands or prompts verbatim. Move the conversation forward by focusing on the latest required action.
43645
-
43646
43886
  5. **No Unnecessary Re-invocations**
43647
- - Only invoke the same tool again if a genuine need arises (e.g., different parameters or updated context).`;
43887
+ - Only invoke the same tool again if a genuine need arises (e.g., different parameters or updated context).
43888
+ 6. **Tool Call Limit**
43889
+ - Do not make more than 5 tool calls in a single message.`;
43648
43890
  };
43649
43891
  var agentsPrompt = (agents, name) => `
43650
43892
  ====
@@ -43771,6 +44013,9 @@ ${instance.prompt}`;
43771
44013
  this.config = config;
43772
44014
  this.#policies = policies;
43773
44015
  }
44016
+ get parameters() {
44017
+ return this.ai.options.parameters;
44018
+ }
43774
44019
  get messages() {
43775
44020
  return this.#messages;
43776
44021
  }
@@ -43967,8 +44212,8 @@ ${instance.prompt}`;
43967
44212
  }
43968
44213
  async#invokeTool(name, args) {
43969
44214
  try {
43970
- const handler14 = this.handlers[name]?.handler;
43971
- if (!handler14) {
44215
+ const handler15 = this.handlers[name]?.handler;
44216
+ if (!handler15) {
43972
44217
  return {
43973
44218
  type: "Error" /* Error */,
43974
44219
  message: responsePrompts.errorInvokeTool(name, "Tool not found"),
@@ -43987,7 +44232,7 @@ ${instance.prompt}`;
43987
44232
  if (resp) {
43988
44233
  return resp;
43989
44234
  }
43990
- return await handler14(this.config.provider, args);
44235
+ return await handler15(this.config.provider, args);
43991
44236
  } catch (error) {
43992
44237
  return {
43993
44238
  type: "Error" /* Error */,
@@ -53179,15 +53424,15 @@ function useKeypress(userHandler) {
53179
53424
  signal.current = userHandler;
53180
53425
  useEffect((rl) => {
53181
53426
  let ignore = false;
53182
- const handler14 = withUpdates((_input, event) => {
53427
+ const handler15 = withUpdates((_input, event) => {
53183
53428
  if (ignore)
53184
53429
  return;
53185
53430
  signal.current(event, rl);
53186
53431
  });
53187
- rl.input.on("keypress", handler14);
53432
+ rl.input.on("keypress", handler15);
53188
53433
  return () => {
53189
53434
  ignore = true;
53190
- rl.input.removeListener("keypress", handler14);
53435
+ rl.input.removeListener("keypress", handler15);
53191
53436
  };
53192
53437
  }, []);
53193
53438
  }
@@ -53369,16 +53614,16 @@ class Emitter {
53369
53614
 
53370
53615
  class SignalExitBase {
53371
53616
  }
53372
- var signalExitWrap = (handler14) => {
53617
+ var signalExitWrap = (handler15) => {
53373
53618
  return {
53374
53619
  onExit(cb, opts) {
53375
- return handler14.onExit(cb, opts);
53620
+ return handler15.onExit(cb, opts);
53376
53621
  },
53377
53622
  load() {
53378
- return handler14.load();
53623
+ return handler15.load();
53379
53624
  },
53380
53625
  unload() {
53381
- return handler14.unload();
53626
+ return handler15.unload();
53382
53627
  }
53383
53628
  };
53384
53629
  };
@@ -58354,6 +58599,7 @@ class Runner {
58354
58599
  [removeFile_default.name]: removeFile_default,
58355
58600
  [renameFile_default.name]: renameFile_default,
58356
58601
  [replaceInFile_default.name]: replaceInFile_default,
58602
+ [editFile_default.name]: editFile_default,
58357
58603
  [searchFiles_default.name]: searchFiles_default,
58358
58604
  [writeToFile_default.name]: writeToFile_default,
58359
58605
  [updateKnowledge_default.name]: updateKnowledge_default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/runner",
3
- "version": "0.8.11",
3
+ "version": "0.8.13",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",