@polka-codes/cli-shared 0.8.11 → 0.8.12

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 +468 -221
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -27496,8 +27496,10 @@ import { join as join2 } from "node:path";
27496
27496
  // ../core/src/AiService/AiServiceBase.ts
27497
27497
  class AiServiceBase {
27498
27498
  usageMeter;
27499
- constructor(usageMeter) {
27500
- this.usageMeter = usageMeter;
27499
+ options;
27500
+ constructor(options) {
27501
+ this.options = options;
27502
+ this.usageMeter = options.usageMeter;
27501
27503
  }
27502
27504
  async* send(systemPrompt, messages) {
27503
27505
  this.usageMeter.checkLimit();
@@ -30983,7 +30985,7 @@ class AnthropicService extends AiServiceBase {
30983
30985
  #client;
30984
30986
  model;
30985
30987
  constructor(options) {
30986
- super(options.usageMeter);
30988
+ super(options);
30987
30989
  this.#options = options;
30988
30990
  this.#client = new Anthropic({
30989
30991
  apiKey: options.apiKey,
@@ -36410,7 +36412,7 @@ class DeepSeekService extends AiServiceBase {
36410
36412
  #client;
36411
36413
  model;
36412
36414
  constructor(options) {
36413
- super(options.usageMeter);
36415
+ super(options);
36414
36416
  this.#client = new openai_default({
36415
36417
  baseURL: "https://api.deepseek.com/v1",
36416
36418
  apiKey: options.apiKey
@@ -36467,7 +36469,7 @@ class OllamaService extends AiServiceBase {
36467
36469
  #client;
36468
36470
  model;
36469
36471
  constructor(options) {
36470
- super(options.usageMeter);
36472
+ super(options);
36471
36473
  this.#client = new openai_default({
36472
36474
  baseURL: `${options.baseUrl || "http://localhost:11434"}/v1`,
36473
36475
  apiKey: "ollama"
@@ -36509,7 +36511,7 @@ class OpenRouterService extends AiServiceBase {
36509
36511
  #modelProviderInfo;
36510
36512
  model;
36511
36513
  constructor(options) {
36512
- super(options.usageMeter);
36514
+ super(options);
36513
36515
  if (!options.model) {
36514
36516
  throw new Error("OpenRouter requires a model");
36515
36517
  }
@@ -36782,73 +36784,98 @@ __export(exports_allTools, {
36782
36784
  writeToFile: () => writeToFile_default,
36783
36785
  updateKnowledge: () => updateKnowledge_default,
36784
36786
  searchFiles: () => searchFiles_default,
36785
- replaceInFile: () => replaceInFile_default,
36786
36787
  renameFile: () => renameFile_default,
36787
36788
  removeFile: () => removeFile_default,
36788
36789
  readFile: () => readFile_default,
36789
36790
  listFiles: () => listFiles_default,
36790
36791
  handOver: () => handOver_default,
36791
36792
  executeCommand: () => executeCommand_default,
36793
+ editFile: () => editFile_default,
36792
36794
  delegate: () => delegate_default,
36793
36795
  attemptCompletion: () => attemptCompletion_default,
36794
36796
  askFollowupQuestion: () => askFollowupQuestion_default
36795
36797
  });
36796
36798
 
36797
- // ../core/src/tools/utils/replaceInFile.ts
36798
- var replaceInFile = async (fileContent, diff) => {
36799
- const blockPattern = /<<<<<+ SEARCH\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
36800
- const blocks = [];
36801
- for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
36802
- blocks.push({ search: match[1], replace: match[2] });
36799
+ // ../core/src/tools/utils/editFile.ts
36800
+ var START_OF_FILE = "<<<START_OF_FILE>>>";
36801
+ var END_OF_FILE = "<<<END_OF_FILE>>>";
36802
+ var editFile = async (fileContent, operations) => {
36803
+ if (!operations || operations.length === 0) {
36804
+ throw new Error("At least one edit operation is required");
36803
36805
  }
36804
- if (blocks.length === 0) {
36805
- throw new Error("No valid diff blocks found.");
36806
+ const originalLines = fileContent.split(`
36807
+ `);
36808
+ let updatedContent = fileContent;
36809
+ for (const operation of operations) {
36810
+ updatedContent = await applyEditOperation(updatedContent, operation, originalLines);
36806
36811
  }
36807
- const findAndReplace = (content, search, replace) => {
36808
- let index = content.indexOf(search);
36809
- if (index !== -1) {
36810
- return content.slice(0, index) + replace + content.slice(index + search.length);
36812
+ return updatedContent;
36813
+ };
36814
+ async function applyEditOperation(fileContent, operation, originalLines) {
36815
+ const { before_text, after_text, new_text, before_text_line_start, after_text_line_start } = operation;
36816
+ if (before_text === START_OF_FILE && after_text === END_OF_FILE) {
36817
+ return new_text;
36818
+ }
36819
+ if (before_text === START_OF_FILE) {
36820
+ if (!after_text) {
36821
+ return new_text + fileContent;
36811
36822
  }
36812
- const trimmedSearch = search.trim();
36813
- const trimmedContent = content.trim();
36814
- const offset = content.indexOf(trimmedContent);
36815
- index = trimmedContent.indexOf(trimmedSearch);
36816
- if (index !== -1) {
36817
- const absoluteIndex = offset + index;
36818
- return content.slice(0, absoluteIndex) + replace + content.slice(absoluteIndex + trimmedSearch.length);
36823
+ const afterIndex = findTextWithHint(fileContent, after_text, after_text_line_start, originalLines);
36824
+ return new_text + fileContent.slice(afterIndex);
36825
+ }
36826
+ if (after_text === END_OF_FILE) {
36827
+ if (!before_text) {
36828
+ return fileContent + new_text;
36819
36829
  }
36820
- const normalizedSearch = trimmedSearch.replace(/\s+/g, " ");
36821
- const normalizedContent = trimmedContent.replace(/\s+/g, " ");
36822
- index = normalizedContent.indexOf(normalizedSearch);
36823
- if (index !== -1) {
36824
- let runningIndex = 0;
36825
- let actualPos = offset;
36826
- for (const segment of trimmedSearch.replace(/\s+/g, " ").split(" ")) {
36827
- const segIndex = content.indexOf(segment, actualPos);
36828
- if (segIndex === -1) {
36829
- break;
36830
- }
36831
- if (runningIndex === 0) {
36832
- actualPos = segIndex;
36833
- } else {
36834
- actualPos = segIndex + segment.length;
36835
- }
36836
- runningIndex++;
36830
+ const beforeIndex = findTextWithHint(fileContent, before_text, before_text_line_start, originalLines);
36831
+ const beforeEndIndex = beforeIndex + before_text.length;
36832
+ return fileContent.slice(0, beforeEndIndex) + new_text;
36833
+ }
36834
+ if (before_text && after_text) {
36835
+ const beforeIndex = findTextWithHint(fileContent, before_text, before_text_line_start, originalLines);
36836
+ const beforeEndIndex = beforeIndex + before_text.length;
36837
+ const afterIndex = findTextWithHint(fileContent, after_text, after_text_line_start, originalLines, beforeEndIndex);
36838
+ return fileContent.slice(0, beforeEndIndex) + new_text + fileContent.slice(afterIndex);
36839
+ }
36840
+ if (before_text) {
36841
+ const beforeIndex = findTextWithHint(fileContent, before_text, before_text_line_start, originalLines);
36842
+ const beforeEndIndex = beforeIndex + before_text.length;
36843
+ return fileContent.slice(0, beforeEndIndex) + new_text + fileContent.slice(beforeEndIndex);
36844
+ }
36845
+ if (after_text) {
36846
+ const afterIndex = findTextWithHint(fileContent, after_text, after_text_line_start, originalLines);
36847
+ return fileContent.slice(0, afterIndex) + new_text + fileContent.slice(afterIndex);
36848
+ }
36849
+ throw new Error("Either before_text or after_text must be specified");
36850
+ }
36851
+ function findTextWithHint(content, searchText, lineHint, originalLines, startIndex = 0) {
36852
+ if (lineHint && lineHint > 0 && lineHint <= originalLines.length) {
36853
+ const hintIndex = getLineStartIndex(originalLines, lineHint - 1);
36854
+ const searchRadius = 5;
36855
+ const windowStart = Math.max(0, hintIndex - searchRadius * 50);
36856
+ const windowEnd = Math.min(content.length, hintIndex + searchRadius * 50);
36857
+ const windowContent = content.slice(windowStart, windowEnd);
36858
+ const relativeIndex = windowContent.indexOf(searchText);
36859
+ if (relativeIndex !== -1) {
36860
+ const absoluteIndex = windowStart + relativeIndex;
36861
+ if (absoluteIndex >= startIndex) {
36862
+ return absoluteIndex;
36837
36863
  }
36838
- const strippedSearch = trimmedSearch.replace(/\s+/g, "");
36839
- const endPos = actualPos;
36840
- const startPos = endPos - strippedSearch.length;
36841
- return content.slice(0, startPos) + replace + content.slice(endPos);
36842
36864
  }
36843
- throw new Error(`Could not find the following text in file:
36844
- ${search}`);
36845
- };
36846
- let updatedFile = fileContent;
36847
- for (const { search, replace } of blocks) {
36848
- updatedFile = findAndReplace(updatedFile, search, replace);
36849
36865
  }
36850
- return updatedFile;
36851
- };
36866
+ const index = content.indexOf(searchText, startIndex);
36867
+ if (index === -1) {
36868
+ throw new Error(`Could not find text: ${searchText}`);
36869
+ }
36870
+ return index;
36871
+ }
36872
+ function getLineStartIndex(lines, lineIndex) {
36873
+ let index = 0;
36874
+ for (let i2 = 0;i2 < lineIndex && i2 < lines.length; i2++) {
36875
+ index += lines[i2].length + 1;
36876
+ }
36877
+ return index;
36878
+ }
36852
36879
  // ../core/src/tools/utils/getArg.ts
36853
36880
  var getString = (args, name, defaultValue) => {
36854
36881
  if (typeof args !== "object" || Array.isArray(args)) {
@@ -36940,6 +36967,61 @@ var getArray = (args, name, defaultValue) => {
36940
36967
  }
36941
36968
  return [ret];
36942
36969
  };
36970
+ // ../core/src/tools/utils/replaceInFile.ts
36971
+ var replaceInFile = async (fileContent, diff) => {
36972
+ const blockPattern = /<<<<<+ SEARCH\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
36973
+ const blocks = [];
36974
+ for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
36975
+ blocks.push({ search: match[1], replace: match[2] });
36976
+ }
36977
+ if (blocks.length === 0) {
36978
+ throw new Error("No valid diff blocks found.");
36979
+ }
36980
+ const findAndReplace = (content, search, replace) => {
36981
+ let index = content.indexOf(search);
36982
+ if (index !== -1) {
36983
+ return content.slice(0, index) + replace + content.slice(index + search.length);
36984
+ }
36985
+ const trimmedSearch = search.trim();
36986
+ const trimmedContent = content.trim();
36987
+ const offset = content.indexOf(trimmedContent);
36988
+ index = trimmedContent.indexOf(trimmedSearch);
36989
+ if (index !== -1) {
36990
+ const absoluteIndex = offset + index;
36991
+ return content.slice(0, absoluteIndex) + replace + content.slice(absoluteIndex + trimmedSearch.length);
36992
+ }
36993
+ const normalizedSearch = trimmedSearch.replace(/\s+/g, " ");
36994
+ const normalizedContent = trimmedContent.replace(/\s+/g, " ");
36995
+ index = normalizedContent.indexOf(normalizedSearch);
36996
+ if (index !== -1) {
36997
+ let runningIndex = 0;
36998
+ let actualPos = offset;
36999
+ for (const segment of trimmedSearch.replace(/\s+/g, " ").split(" ")) {
37000
+ const segIndex = content.indexOf(segment, actualPos);
37001
+ if (segIndex === -1) {
37002
+ break;
37003
+ }
37004
+ if (runningIndex === 0) {
37005
+ actualPos = segIndex;
37006
+ } else {
37007
+ actualPos = segIndex + segment.length;
37008
+ }
37009
+ runningIndex++;
37010
+ }
37011
+ const strippedSearch = trimmedSearch.replace(/\s+/g, "");
37012
+ const endPos = actualPos;
37013
+ const startPos = endPos - strippedSearch.length;
37014
+ return content.slice(0, startPos) + replace + content.slice(endPos);
37015
+ }
37016
+ throw new Error(`Could not find the following text in file:
37017
+ ${search}`);
37018
+ };
37019
+ let updatedFile = fileContent;
37020
+ for (const { search, replace } of blocks) {
37021
+ updatedFile = findAndReplace(updatedFile, search, replace);
37022
+ }
37023
+ return updatedFile;
37024
+ };
36943
37025
  // ../core/src/tools/askFollowupQuestion.ts
36944
37026
  var toolInfo = {
36945
37027
  name: "ask_followup_question",
@@ -37386,125 +37468,8 @@ var readFile_default = {
37386
37468
  handler: handler6,
37387
37469
  isAvailable: isAvailable6
37388
37470
  };
37389
- // ../core/src/tools/replaceInFile.ts
37390
- var toolInfo7 = {
37391
- name: "replace_in_file",
37392
- 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.",
37393
- parameters: [
37394
- {
37395
- name: "path",
37396
- description: "The path of the file to modify",
37397
- required: true,
37398
- usageValue: "File path here"
37399
- },
37400
- {
37401
- name: "diff",
37402
- description: `One or more SEARCH/REPLACE blocks following this exact format:
37403
- \`\`\`
37404
- <<<<<<< SEARCH
37405
- [exact content to find]
37406
- =======
37407
- [new content to replace with]
37408
- >>>>>>> REPLACE
37409
- \`\`\`
37410
- Critical rules:
37411
- 1. SEARCH content must match the associated file section to find EXACTLY:
37412
- * Match character-for-character including whitespace, indentation, line endings
37413
- * Include all comments, docstrings, etc.
37414
- 2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
37415
- * Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
37416
- * Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
37417
- * When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
37418
- 3. Keep SEARCH/REPLACE blocks concise:
37419
- * Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
37420
- * Include just the changing lines, and a few surrounding lines if needed for uniqueness.
37421
- * Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
37422
- * Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
37423
- 4. Special operations:
37424
- * To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
37425
- * To delete code: Use empty REPLACE section`,
37426
- required: true,
37427
- usageValue: "Search and replace blocks here"
37428
- }
37429
- ],
37430
- examples: [
37431
- {
37432
- description: "Request to replace sections of content in a file",
37433
- parameters: [
37434
- {
37435
- name: "path",
37436
- value: "src/main.js"
37437
- },
37438
- {
37439
- name: "diff",
37440
- value: `
37441
- <<<<<<< SEARCH
37442
- import React from 'react';
37443
- =======
37444
- import React, { useState } from 'react';
37445
- >>>>>>> REPLACE
37446
-
37447
- <<<<<<< SEARCH
37448
- function handleSubmit() {
37449
- saveData();
37450
- setLoading(false);
37451
- }
37452
-
37453
- =======
37454
- >>>>>>> REPLACE
37455
-
37456
- <<<<<<< SEARCH
37457
- return (
37458
- <div>
37459
- =======
37460
- function handleSubmit() {
37461
- saveData();
37462
- setLoading(false);
37463
- }
37464
-
37465
- return (
37466
- <div>
37467
- >>>>>>> REPLACE
37468
- `
37469
- }
37470
- ]
37471
- }
37472
- ],
37473
- permissionLevel: 2 /* Write */
37474
- };
37475
- var handler7 = async (provider, args) => {
37476
- if (!provider.readFile || !provider.writeFile) {
37477
- return {
37478
- type: "Error" /* Error */,
37479
- message: "Not possible to replace in file. Abort."
37480
- };
37481
- }
37482
- const path = getString(args, "path");
37483
- const diff = getString(args, "diff");
37484
- const fileContent = await provider.readFile(path);
37485
- if (fileContent == null) {
37486
- return {
37487
- type: "Error" /* Error */,
37488
- message: `<error><replace_in_file_path>${path}</replace_in_file_path><error_message>File not found</error_message></error>`
37489
- };
37490
- }
37491
- const result = await replaceInFile(fileContent, diff);
37492
- await provider.writeFile(path, result);
37493
- return {
37494
- type: "Reply" /* Reply */,
37495
- message: `<replace_in_file_path>${path}</replace_in_file_path>`
37496
- };
37497
- };
37498
- var isAvailable7 = (provider) => {
37499
- return !!provider.readFile && !!provider.writeFile;
37500
- };
37501
- var replaceInFile_default = {
37502
- ...toolInfo7,
37503
- handler: handler7,
37504
- isAvailable: isAvailable7
37505
- };
37506
37471
  // ../core/src/tools/searchFiles.ts
37507
- var toolInfo8 = {
37472
+ var toolInfo7 = {
37508
37473
  name: "search_files",
37509
37474
  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.",
37510
37475
  parameters: [
@@ -37548,7 +37513,7 @@ var toolInfo8 = {
37548
37513
  ],
37549
37514
  permissionLevel: 1 /* Read */
37550
37515
  };
37551
- var handler8 = async (provider, args) => {
37516
+ var handler7 = async (provider, args) => {
37552
37517
  if (!provider.searchFiles) {
37553
37518
  return {
37554
37519
  type: "Error" /* Error */,
@@ -37571,18 +37536,18 @@ ${files.join(`
37571
37536
  `
37572
37537
  };
37573
37538
  };
37574
- var isAvailable8 = (provider) => {
37539
+ var isAvailable7 = (provider) => {
37575
37540
  return !!provider.searchFiles;
37576
37541
  };
37577
37542
  var searchFiles_default = {
37578
- ...toolInfo8,
37579
- handler: handler8,
37580
- isAvailable: isAvailable8
37543
+ ...toolInfo7,
37544
+ handler: handler7,
37545
+ isAvailable: isAvailable7
37581
37546
  };
37582
37547
  // ../core/src/tools/updateKnowledge.ts
37583
37548
  var import_yaml = __toESM(require_dist(), 1);
37584
37549
  import { join } from "node:path";
37585
- var toolInfo9 = {
37550
+ var toolInfo8 = {
37586
37551
  name: "update_knowledge",
37587
37552
  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.",
37588
37553
  parameters: [
@@ -37759,7 +37724,7 @@ function deepMerge(target, source) {
37759
37724
  }
37760
37725
  return output;
37761
37726
  }
37762
- var handler9 = async (provider, args) => {
37727
+ var handler8 = async (provider, args) => {
37763
37728
  if (!provider.readFile || !provider.writeFile) {
37764
37729
  return {
37765
37730
  type: "Error" /* Error */,
@@ -37831,16 +37796,16 @@ var handler9 = async (provider, args) => {
37831
37796
  };
37832
37797
  }
37833
37798
  };
37834
- var isAvailable9 = (provider) => {
37799
+ var isAvailable8 = (provider) => {
37835
37800
  return !!provider.readFile && !!provider.writeFile;
37836
37801
  };
37837
37802
  var updateKnowledge_default = {
37838
- ...toolInfo9,
37839
- handler: handler9,
37840
- isAvailable: isAvailable9
37803
+ ...toolInfo8,
37804
+ handler: handler8,
37805
+ isAvailable: isAvailable8
37841
37806
  };
37842
37807
  // ../core/src/tools/writeToFile.ts
37843
- var toolInfo10 = {
37808
+ var toolInfo9 = {
37844
37809
  name: "write_to_file",
37845
37810
  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;`.",
37846
37811
  parameters: [
@@ -37885,7 +37850,7 @@ export default App;
37885
37850
  ],
37886
37851
  permissionLevel: 2 /* Write */
37887
37852
  };
37888
- var handler10 = async (provider, args) => {
37853
+ var handler9 = async (provider, args) => {
37889
37854
  if (!provider.writeFile) {
37890
37855
  return {
37891
37856
  type: "Error" /* Error */,
@@ -37900,16 +37865,16 @@ var handler10 = async (provider, args) => {
37900
37865
  message: `<write_to_file_path>${path}</write_to_file_path><status>Success</status>`
37901
37866
  };
37902
37867
  };
37903
- var isAvailable10 = (provider) => {
37868
+ var isAvailable9 = (provider) => {
37904
37869
  return !!provider.writeFile;
37905
37870
  };
37906
37871
  var writeToFile_default = {
37907
- ...toolInfo10,
37908
- handler: handler10,
37909
- isAvailable: isAvailable10
37872
+ ...toolInfo9,
37873
+ handler: handler9,
37874
+ isAvailable: isAvailable9
37910
37875
  };
37911
37876
  // ../core/src/tools/handOver.ts
37912
- var toolInfo11 = {
37877
+ var toolInfo10 = {
37913
37878
  name: "hand_over",
37914
37879
  description: "Hand over the current task to another agent to complete. This tool MUST NOT to be used with any other tool.",
37915
37880
  parameters: [
@@ -37963,7 +37928,7 @@ var toolInfo11 = {
37963
37928
  ],
37964
37929
  permissionLevel: 0 /* None */
37965
37930
  };
37966
- var handler11 = async (_provider, args) => {
37931
+ var handler10 = async (_provider, args) => {
37967
37932
  const agentName = getString(args, "agent_name");
37968
37933
  const task = getString(args, "task");
37969
37934
  const context = getString(args, "context", undefined);
@@ -37976,16 +37941,16 @@ var handler11 = async (_provider, args) => {
37976
37941
  files
37977
37942
  };
37978
37943
  };
37979
- var isAvailable11 = (_provider) => {
37944
+ var isAvailable10 = (_provider) => {
37980
37945
  return true;
37981
37946
  };
37982
37947
  var handOver_default = {
37983
- ...toolInfo11,
37984
- handler: handler11,
37985
- isAvailable: isAvailable11
37948
+ ...toolInfo10,
37949
+ handler: handler10,
37950
+ isAvailable: isAvailable10
37986
37951
  };
37987
37952
  // ../core/src/tools/removeFile.ts
37988
- var toolInfo12 = {
37953
+ var toolInfo11 = {
37989
37954
  name: "remove_file",
37990
37955
  description: "Request to remove a file at the specified path.",
37991
37956
  parameters: [
@@ -38009,7 +37974,7 @@ var toolInfo12 = {
38009
37974
  ],
38010
37975
  permissionLevel: 2 /* Write */
38011
37976
  };
38012
- var handler12 = async (provider, args) => {
37977
+ var handler11 = async (provider, args) => {
38013
37978
  if (!provider.removeFile) {
38014
37979
  return {
38015
37980
  type: "Error" /* Error */,
@@ -38023,27 +37988,27 @@ var handler12 = async (provider, args) => {
38023
37988
  message: `<remove_file_path>${path}</remove_file_path><status>Success</status>`
38024
37989
  };
38025
37990
  };
38026
- var isAvailable12 = (provider) => {
37991
+ var isAvailable11 = (provider) => {
38027
37992
  return !!provider.removeFile;
38028
37993
  };
38029
37994
  var removeFile_default = {
38030
- ...toolInfo12,
38031
- handler: handler12,
38032
- isAvailable: isAvailable12
37995
+ ...toolInfo11,
37996
+ handler: handler11,
37997
+ isAvailable: isAvailable11
38033
37998
  };
38034
37999
  // ../core/src/tools/renameFile.ts
38035
- var toolInfo13 = {
38000
+ var toolInfo12 = {
38036
38001
  name: "rename_file",
38037
38002
  description: "Request to rename a file from source path to target path.",
38038
38003
  parameters: [
38039
38004
  {
38040
- name: "sourcePath",
38005
+ name: "source_path",
38041
38006
  description: "The current path of the file",
38042
38007
  required: true,
38043
38008
  usageValue: "Source file path here"
38044
38009
  },
38045
38010
  {
38046
- name: "targetPath",
38011
+ name: "target_path",
38047
38012
  description: "The new path for the file",
38048
38013
  required: true,
38049
38014
  usageValue: "Target file path here"
@@ -38054,11 +38019,11 @@ var toolInfo13 = {
38054
38019
  description: "Request to rename a file",
38055
38020
  parameters: [
38056
38021
  {
38057
- name: "sourcePath",
38022
+ name: "source_path",
38058
38023
  value: "src/old-name.js"
38059
38024
  },
38060
38025
  {
38061
- name: "targetPath",
38026
+ name: "target_path",
38062
38027
  value: "src/new-name.js"
38063
38028
  }
38064
38029
  ]
@@ -38066,29 +38031,308 @@ var toolInfo13 = {
38066
38031
  ],
38067
38032
  permissionLevel: 2 /* Write */
38068
38033
  };
38069
- var handler13 = async (provider, args) => {
38034
+ var handler12 = async (provider, args) => {
38070
38035
  if (!provider.renameFile) {
38071
38036
  return {
38072
38037
  type: "Error" /* Error */,
38073
38038
  message: "Not possible to rename file. Abort."
38074
38039
  };
38075
38040
  }
38076
- const sourcePath = getString(args, "sourcePath");
38077
- const targetPath = getString(args, "targetPath");
38041
+ const sourcePath = getString(args, "source_path");
38042
+ const targetPath = getString(args, "target_path");
38078
38043
  await provider.renameFile(sourcePath, targetPath);
38079
38044
  return {
38080
38045
  type: "Reply" /* Reply */,
38081
38046
  message: `<rename_file_path>${targetPath}</rename_file_path><status>Success</status>`
38082
38047
  };
38083
38048
  };
38084
- var isAvailable13 = (provider) => {
38049
+ var isAvailable12 = (provider) => {
38085
38050
  return !!provider.renameFile;
38086
38051
  };
38087
38052
  var renameFile_default = {
38053
+ ...toolInfo12,
38054
+ handler: handler12,
38055
+ isAvailable: isAvailable12
38056
+ };
38057
+ // ../core/src/tools/editFile.ts
38058
+ var toolInfo13 = {
38059
+ name: "edit_file",
38060
+ description: "Request to edit file contents using before/after text anchors with flexible operations. Supports multiple edit operations in a single call.",
38061
+ parameters: [
38062
+ {
38063
+ name: "path",
38064
+ description: "The path of the file to edit",
38065
+ required: true,
38066
+ usageValue: "File path here"
38067
+ },
38068
+ {
38069
+ name: "operations",
38070
+ description: "Edit operation with before_text, after_text, new_text, and optional line range hints",
38071
+ required: true,
38072
+ allowMultiple: true,
38073
+ children: [
38074
+ {
38075
+ name: "before_text",
38076
+ description: `Text to find as the start anchor (use ${START_OF_FILE} for file start)`,
38077
+ required: false,
38078
+ usageValue: "Text before the edit location"
38079
+ },
38080
+ {
38081
+ name: "after_text",
38082
+ description: `Text to find as the end anchor (use ${END_OF_FILE} for file end)`,
38083
+ required: false,
38084
+ usageValue: "Text after the edit location"
38085
+ },
38086
+ {
38087
+ name: "new_text",
38088
+ description: "Text to replace the content between before_text and after_text",
38089
+ required: true,
38090
+ usageValue: "New text content"
38091
+ },
38092
+ {
38093
+ name: "before_text_line_start",
38094
+ description: "Optional line number hint for before_text location (1-based)",
38095
+ required: false,
38096
+ usageValue: "10"
38097
+ },
38098
+ {
38099
+ name: "after_text_line_start",
38100
+ description: "Optional line number hint for after_text location (1-based)",
38101
+ required: false,
38102
+ usageValue: "20"
38103
+ }
38104
+ ],
38105
+ usageValue: "operations here"
38106
+ }
38107
+ ],
38108
+ examples: [
38109
+ {
38110
+ description: "Replace content between two text anchors",
38111
+ parameters: [
38112
+ {
38113
+ name: "path",
38114
+ value: "src/main.ts"
38115
+ },
38116
+ {
38117
+ name: "operations",
38118
+ value: {
38119
+ before_text: "function oldFunction() {",
38120
+ after_text: "}",
38121
+ new_text: `
38122
+ return "new implementation";
38123
+ `
38124
+ }
38125
+ }
38126
+ ]
38127
+ },
38128
+ {
38129
+ description: "Insert at start of file",
38130
+ parameters: [
38131
+ {
38132
+ name: "path",
38133
+ value: "src/header.ts"
38134
+ },
38135
+ {
38136
+ name: "operations",
38137
+ value: {
38138
+ before_text: START_OF_FILE,
38139
+ after_text: "export",
38140
+ new_text: `// File header comment
38141
+ `
38142
+ }
38143
+ }
38144
+ ]
38145
+ },
38146
+ {
38147
+ description: "Multiple operations in one call",
38148
+ parameters: [
38149
+ {
38150
+ name: "path",
38151
+ value: "src/utils.ts"
38152
+ },
38153
+ {
38154
+ name: "operations",
38155
+ value: [
38156
+ {
38157
+ before_text: "import React",
38158
+ after_text: 'from "react"',
38159
+ new_text: ", { useState }"
38160
+ },
38161
+ {
38162
+ before_text: "function Component() {",
38163
+ after_text: "return (",
38164
+ new_text: `
38165
+ const [state, setState] = useState(false);
38166
+ `
38167
+ }
38168
+ ]
38169
+ }
38170
+ ]
38171
+ }
38172
+ ],
38173
+ permissionLevel: 2 /* Write */
38174
+ };
38175
+ var handler13 = async (provider, args) => {
38176
+ if (!provider.readFile || !provider.writeFile) {
38177
+ return {
38178
+ type: "Error" /* Error */,
38179
+ message: "Not possible to edit file. Abort."
38180
+ };
38181
+ }
38182
+ const path = getString(args, "path");
38183
+ const operations = getArray(args, "operations");
38184
+ if (!operations || operations.length === 0) {
38185
+ return {
38186
+ type: "Error" /* Error */,
38187
+ message: `<error><edit_file_path>${path}</edit_file_path><error_message>At least one edit operation is required</error_message></error>`
38188
+ };
38189
+ }
38190
+ const fileContent = await provider.readFile(path);
38191
+ if (fileContent == null) {
38192
+ return {
38193
+ type: "Error" /* Error */,
38194
+ message: `<error><edit_file_path>${path}</edit_file_path><error_message>File not found</error_message></error>`
38195
+ };
38196
+ }
38197
+ try {
38198
+ const result = await editFile(fileContent, operations);
38199
+ await provider.writeFile(path, result);
38200
+ return {
38201
+ type: "Reply" /* Reply */,
38202
+ message: `<edit_file_path>${path}</edit_file_path>`
38203
+ };
38204
+ } catch (error) {
38205
+ return {
38206
+ type: "Error" /* Error */,
38207
+ message: `<error><edit_file_path>${path}</edit_file_path><error_message>${error instanceof Error ? error.message : String(error)}</error_message></error>`
38208
+ };
38209
+ }
38210
+ };
38211
+ var isAvailable13 = (provider) => {
38212
+ return !!provider.readFile && !!provider.writeFile;
38213
+ };
38214
+ var editFile_default = {
38088
38215
  ...toolInfo13,
38089
38216
  handler: handler13,
38090
38217
  isAvailable: isAvailable13
38091
38218
  };
38219
+ // ../core/src/tools/replaceInFile.ts
38220
+ var toolInfo14 = {
38221
+ name: "replace_in_file",
38222
+ 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.",
38223
+ parameters: [
38224
+ {
38225
+ name: "path",
38226
+ description: "The path of the file to modify",
38227
+ required: true,
38228
+ usageValue: "File path here"
38229
+ },
38230
+ {
38231
+ name: "diff",
38232
+ description: `One or more SEARCH/REPLACE blocks following this exact format:
38233
+ \`\`\`
38234
+ <<<<<<< SEARCH
38235
+ [exact content to find]
38236
+ =======
38237
+ [new content to replace with]
38238
+ >>>>>>> REPLACE
38239
+ \`\`\`
38240
+ Critical rules:
38241
+ 1. SEARCH content must match the associated file section to find EXACTLY:
38242
+ * Match character-for-character including whitespace, indentation, line endings
38243
+ * Include all comments, docstrings, etc.
38244
+ 2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
38245
+ * Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
38246
+ * Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
38247
+ * When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
38248
+ 3. Keep SEARCH/REPLACE blocks concise:
38249
+ * Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
38250
+ * Include just the changing lines, and a few surrounding lines if needed for uniqueness.
38251
+ * Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
38252
+ * Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
38253
+ 4. Special operations:
38254
+ * To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
38255
+ * To delete code: Use empty REPLACE section`,
38256
+ required: true,
38257
+ usageValue: "Search and replace blocks here"
38258
+ }
38259
+ ],
38260
+ examples: [
38261
+ {
38262
+ description: "Request to replace sections of content in a file",
38263
+ parameters: [
38264
+ {
38265
+ name: "path",
38266
+ value: "src/main.js"
38267
+ },
38268
+ {
38269
+ name: "diff",
38270
+ value: `
38271
+ <<<<<<< SEARCH
38272
+ import React from 'react';
38273
+ =======
38274
+ import React, { useState } from 'react';
38275
+ >>>>>>> REPLACE
38276
+
38277
+ <<<<<<< SEARCH
38278
+ function handleSubmit() {
38279
+ saveData();
38280
+ setLoading(false);
38281
+ }
38282
+
38283
+ =======
38284
+ >>>>>>> REPLACE
38285
+
38286
+ <<<<<<< SEARCH
38287
+ return (
38288
+ <div>
38289
+ =======
38290
+ function handleSubmit() {
38291
+ saveData();
38292
+ setLoading(false);
38293
+ }
38294
+
38295
+ return (
38296
+ <div>
38297
+ >>>>>>> REPLACE
38298
+ `
38299
+ }
38300
+ ]
38301
+ }
38302
+ ],
38303
+ permissionLevel: 2 /* Write */
38304
+ };
38305
+ var handler14 = async (provider, args) => {
38306
+ if (!provider.readFile || !provider.writeFile) {
38307
+ return {
38308
+ type: "Error" /* Error */,
38309
+ message: "Not possible to replace in file. Abort."
38310
+ };
38311
+ }
38312
+ const path = getString(args, "path");
38313
+ const diff = getString(args, "diff");
38314
+ const fileContent = await provider.readFile(path);
38315
+ if (fileContent == null) {
38316
+ return {
38317
+ type: "Error" /* Error */,
38318
+ message: `<error><replace_in_file_path>${path}</replace_in_file_path><error_message>File not found</error_message></error>`
38319
+ };
38320
+ }
38321
+ const result = await replaceInFile(fileContent, diff);
38322
+ await provider.writeFile(path, result);
38323
+ return {
38324
+ type: "Reply" /* Reply */,
38325
+ message: `<replace_in_file_path>${path}</replace_in_file_path>`
38326
+ };
38327
+ };
38328
+ var isAvailable14 = (provider) => {
38329
+ return !!provider.readFile && !!provider.writeFile;
38330
+ };
38331
+ var replaceInFile_default = {
38332
+ ...toolInfo14,
38333
+ handler: handler14,
38334
+ isAvailable: isAvailable14
38335
+ };
38092
38336
  // ../core/src/getAvailableTools.ts
38093
38337
  var getAvailableTools = ({
38094
38338
  provider: provider2,
@@ -38505,6 +38749,9 @@ ${instance.prompt}`;
38505
38749
  this.config = config;
38506
38750
  this.#policies = policies;
38507
38751
  }
38752
+ get parameters() {
38753
+ return this.ai.options.parameters;
38754
+ }
38508
38755
  get messages() {
38509
38756
  return this.#messages;
38510
38757
  }
@@ -38701,8 +38948,8 @@ ${instance.prompt}`;
38701
38948
  }
38702
38949
  async#invokeTool(name, args) {
38703
38950
  try {
38704
- const handler14 = this.handlers[name]?.handler;
38705
- if (!handler14) {
38951
+ const handler15 = this.handlers[name]?.handler;
38952
+ if (!handler15) {
38706
38953
  return {
38707
38954
  type: "Error" /* Error */,
38708
38955
  message: responsePrompts.errorInvokeTool(name, "Tool not found"),
@@ -38721,7 +38968,7 @@ ${instance.prompt}`;
38721
38968
  if (resp) {
38722
38969
  return resp;
38723
38970
  }
38724
- return await handler14(this.config.provider, args);
38971
+ return await handler15(this.config.provider, args);
38725
38972
  } catch (error) {
38726
38973
  return {
38727
38974
  type: "Error" /* Error */,
@@ -47927,15 +48174,15 @@ function useKeypress(userHandler) {
47927
48174
  signal.current = userHandler;
47928
48175
  useEffect((rl) => {
47929
48176
  let ignore = false;
47930
- const handler14 = withUpdates((_input, event) => {
48177
+ const handler15 = withUpdates((_input, event) => {
47931
48178
  if (ignore)
47932
48179
  return;
47933
48180
  signal.current(event, rl);
47934
48181
  });
47935
- rl.input.on("keypress", handler14);
48182
+ rl.input.on("keypress", handler15);
47936
48183
  return () => {
47937
48184
  ignore = true;
47938
- rl.input.removeListener("keypress", handler14);
48185
+ rl.input.removeListener("keypress", handler15);
47939
48186
  };
47940
48187
  }, []);
47941
48188
  }
@@ -48117,16 +48364,16 @@ class Emitter {
48117
48364
 
48118
48365
  class SignalExitBase {
48119
48366
  }
48120
- var signalExitWrap = (handler14) => {
48367
+ var signalExitWrap = (handler15) => {
48121
48368
  return {
48122
48369
  onExit(cb, opts) {
48123
- return handler14.onExit(cb, opts);
48370
+ return handler15.onExit(cb, opts);
48124
48371
  },
48125
48372
  load() {
48126
- return handler14.load();
48373
+ return handler15.load();
48127
48374
  },
48128
48375
  unload() {
48129
- return handler14.unload();
48376
+ return handler15.unload();
48130
48377
  }
48131
48378
  };
48132
48379
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli-shared",
3
- "version": "0.8.11",
3
+ "version": "0.8.12",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",