@polka-codes/cli-shared 0.9.3 → 0.9.5

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 +110 -43
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -27185,7 +27185,17 @@ var toolInfo7 = {
27185
27185
  return true;
27186
27186
  }
27187
27187
  return val;
27188
- }, exports_external.boolean().optional().default(true)).describe("Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.").meta({ usageValue: "true or false (optional)" })
27188
+ }, exports_external.boolean().optional().default(true)).describe("Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.").meta({ usageValue: "true or false (optional)" }),
27189
+ includeIgnored: exports_external.preprocess((val) => {
27190
+ if (typeof val === "string") {
27191
+ const lower = val.toLowerCase();
27192
+ if (lower === "false")
27193
+ return false;
27194
+ if (lower === "true")
27195
+ return true;
27196
+ }
27197
+ return val;
27198
+ }, exports_external.boolean().optional().default(false)).describe("Whether to include ignored files. Use true to include files ignored by .gitignore.").meta({ usageValue: "true or false (optional)" })
27189
27199
  }).meta({
27190
27200
  examples: [
27191
27201
  {
@@ -27206,8 +27216,8 @@ var handler7 = async (provider, args) => {
27206
27216
  message: "Not possible to list files. Abort."
27207
27217
  };
27208
27218
  }
27209
- const { path, maxCount, recursive } = toolInfo7.parameters.parse(args);
27210
- const [files, limitReached] = await provider.listFiles(path, recursive, maxCount);
27219
+ const { path, maxCount, recursive, includeIgnored } = toolInfo7.parameters.parse(args);
27220
+ const [files, limitReached] = await provider.listFiles(path, recursive, maxCount, includeIgnored);
27211
27221
  return {
27212
27222
  type: "Reply" /* Reply */,
27213
27223
  message: `<list_files_path>${path}</list_files_path>
@@ -27236,7 +27246,17 @@ var toolInfo8 = {
27236
27246
  return [];
27237
27247
  const values = Array.isArray(val) ? val : [val];
27238
27248
  return values.flatMap((i) => typeof i === "string" ? i.split(",") : []).filter((s) => s.length > 0);
27239
- }, exports_external.array(exports_external.string())).describe("The path of the file to read").meta({ usageValue: "Comma separated paths here" })
27249
+ }, exports_external.array(exports_external.string())).describe("The path of the file to read").meta({ usageValue: "Comma separated paths here" }),
27250
+ includeIgnored: exports_external.preprocess((val) => {
27251
+ if (typeof val === "string") {
27252
+ const lower = val.toLowerCase();
27253
+ if (lower === "false")
27254
+ return false;
27255
+ if (lower === "true")
27256
+ return true;
27257
+ }
27258
+ return val;
27259
+ }, exports_external.boolean().optional().default(false)).describe("Whether to include ignored files. Use true to include files ignored by .gitignore.").meta({ usageValue: "true or false (optional)" })
27240
27260
  }).meta({
27241
27261
  examples: [
27242
27262
  {
@@ -27262,10 +27282,10 @@ var handler8 = async (provider, args) => {
27262
27282
  message: "Not possible to read file. Abort."
27263
27283
  };
27264
27284
  }
27265
- const { path: paths } = toolInfo8.parameters.parse(args);
27285
+ const { path: paths, includeIgnored } = toolInfo8.parameters.parse(args);
27266
27286
  const resp = [];
27267
27287
  for (const path of paths) {
27268
- const fileContent = await provider.readFile(path);
27288
+ const fileContent = await provider.readFile(path, includeIgnored);
27269
27289
  if (!fileContent) {
27270
27290
  resp.push(`<read_file_file_content path="${path}" file_not_found="true" />`);
27271
27291
  } else {
@@ -27575,7 +27595,7 @@ var handler11 = async (provider, args) => {
27575
27595
  }
27576
27596
  try {
27577
27597
  const { path, diff } = toolInfo11.parameters.parse(args);
27578
- const fileContent = await provider.readFile(path);
27598
+ const fileContent = await provider.readFile(path, false);
27579
27599
  if (fileContent == null) {
27580
27600
  return {
27581
27601
  type: "Error" /* Error */,
@@ -50997,23 +51017,30 @@ ${instance.prompt}`;
50997
51017
  const requestTimeoutSeconds = this.config.requestTimeoutSeconds ?? 90;
50998
51018
  let respMessages = [];
50999
51019
  for (let i = 0;i < retryCount; i++) {
51020
+ if (this.#aborted) {
51021
+ break;
51022
+ }
51000
51023
  respMessages = [];
51001
51024
  let timeout;
51025
+ let requestAbortController;
51026
+ requestAbortController = new AbortController;
51027
+ this.#abortController = requestAbortController;
51002
51028
  const resetTimeout = () => {
51003
51029
  if (timeout) {
51004
51030
  clearTimeout(timeout);
51005
51031
  }
51006
- if (requestTimeoutSeconds > 0) {
51032
+ if (requestTimeoutSeconds > 0 && requestAbortController) {
51007
51033
  timeout = setTimeout(() => {
51008
- console.debug(`No data received for ${requestTimeoutSeconds} seconds. Aborting request.`);
51009
- this.abort();
51034
+ console.debug(`Request timeout after ${requestTimeoutSeconds} seconds. Canceling current request attempt ${i + 1}/${retryCount}.`);
51035
+ requestAbortController?.abort();
51010
51036
  }, requestTimeoutSeconds * 1000);
51011
51037
  }
51012
51038
  };
51013
- this.#abortController = new AbortController;
51014
51039
  try {
51040
+ resetTimeout();
51015
51041
  const streamTextOptions = {
51016
51042
  model: this.ai,
51043
+ temperature: 0,
51017
51044
  messages,
51018
51045
  providerOptions: this.config.parameters?.providerOptions,
51019
51046
  onChunk: async ({ chunk }) => {
@@ -51033,7 +51060,7 @@ ${instance.prompt}`;
51033
51060
  onError: async (error81) => {
51034
51061
  console.error("Error in stream:", error81);
51035
51062
  },
51036
- abortSignal: this.#abortController.signal
51063
+ abortSignal: requestAbortController.signal
51037
51064
  };
51038
51065
  if (this.config.toolFormat === "native") {
51039
51066
  streamTextOptions.tools = this.#toolSet;
@@ -51046,11 +51073,19 @@ ${instance.prompt}`;
51046
51073
  });
51047
51074
  const resp = await stream.response;
51048
51075
  respMessages = resp.messages;
51076
+ if (timeout) {
51077
+ clearTimeout(timeout);
51078
+ timeout = undefined;
51079
+ }
51049
51080
  } catch (error81) {
51050
51081
  if (error81 instanceof Error && error81.name === "AbortError") {
51051
- break;
51082
+ if (this.#aborted) {
51083
+ break;
51084
+ }
51085
+ console.debug(`Request attempt ${i + 1} timed out, will retry`);
51086
+ } else {
51087
+ console.error("Error in stream:", error81);
51052
51088
  }
51053
- console.error("Error in stream:", error81);
51054
51089
  } finally {
51055
51090
  if (timeout) {
51056
51091
  clearTimeout(timeout);
@@ -51062,16 +51097,26 @@ ${instance.prompt}`;
51062
51097
  if (this.#aborted) {
51063
51098
  break;
51064
51099
  }
51065
- console.debug(`Retrying request ${i + 1} of ${retryCount}`);
51100
+ if (i < retryCount - 1) {
51101
+ console.debug(`Retrying request ${i + 2} of ${retryCount}`);
51102
+ }
51066
51103
  }
51067
51104
  if (respMessages.length === 0) {
51068
51105
  if (this.#aborted) {
51069
51106
  return [];
51070
51107
  }
51071
- throw new Error("No assistant message received");
51108
+ throw new Error("No assistant message received after all retry attempts");
51072
51109
  }
51073
51110
  this.#messages.push(...respMessages);
51074
51111
  if (this.config.toolFormat === "native") {
51112
+ const assistantText = respMessages.map((msg) => {
51113
+ if (typeof msg.content === "string") {
51114
+ return msg.content;
51115
+ }
51116
+ return msg.content.map((part) => part.type === "text" || part.type === "reasoning" ? part.text : "").join("");
51117
+ }).join(`
51118
+ `);
51119
+ await this.#callback({ kind: "EndRequest" /* EndRequest */, agent: this, message: assistantText });
51075
51120
  return respMessages.flatMap((msg) => {
51076
51121
  if (msg.role === "assistant") {
51077
51122
  const content = msg.content;
@@ -51079,7 +51124,7 @@ ${instance.prompt}`;
51079
51124
  return [{ type: "text", content }];
51080
51125
  }
51081
51126
  return content.flatMap((part) => {
51082
- if (part.type === "text") {
51127
+ if (part.type === "text" || part.type === "reasoning") {
51083
51128
  return [{ type: "text", content: part.text }];
51084
51129
  }
51085
51130
  if (part.type === "tool-call") {
@@ -52035,37 +52080,48 @@ var prompt5 = `
52035
52080
 
52036
52081
  You are a senior software engineer reviewing code changes.
52037
52082
 
52083
+ ## Critical Instructions
52084
+ **ONLY review the actual changes shown in the diff.** Do not comment on existing code that wasn't modified.
52085
+
52038
52086
  ## Viewing Changes
52039
- - Use **git_diff** to inspect code.
52040
- - **Pull request**: use the provided commit range.
52041
- - **Local changes**: diff staged or unstaged files.
52087
+ - **Use git_diff** to inspect the actual code changes for each relevant file.
52088
+ - **Pull request**: use the provided commit range for the git_diff tool.
52089
+ - **Local changes**: diff staged or unstaged files using the git_diff tool.
52042
52090
  - If a pull request is present you may receive:
52043
52091
  - <pr_title>
52044
52092
  - <pr_description>
52045
52093
  - <commit_messages>
52046
52094
  - A <review_instructions> tag tells you the focus of the review.
52095
+ - File status information is provided in <file_status> - use this to understand which files were modified, added, deleted, or renamed.
52096
+
52097
+ ## Review Guidelines
52098
+ Focus exclusively on the changed lines (+ additions, - deletions, modified lines):
52099
+ - **Specific issues**: Point to exact problems in the changed code with line references
52100
+ - **Actionable fixes**: Provide concrete solutions, not vague suggestions
52101
+ - **Clear reasoning**: Explain why each issue matters and how to fix it
52102
+ - **Avoid generic advice**: No generic suggestions like "add more tests", "improve documentation", or "follow best practices" unless directly related to a specific problem in the diff
52047
52103
 
52048
- ## Focus Areas
52049
- - Readability and maintainability
52050
- - Correctness, edge cases, potential bugs
52051
- - Performance implications
52052
- - Clarity of intent
52053
- - Best-practice adherence
52104
+ ## What NOT to review
52105
+ - Existing unchanged code
52106
+ - Overall project structure or architecture (unless directly impacted by changes)
52107
+ - Generic best practices unrelated to the specific changes
52108
+ - Missing features or functionality not part of this diff
52054
52109
 
52055
52110
  ## Output Format
52056
52111
  Do **not** include praise or positive feedback. Ignore generated files such as lock files.
52112
+ Only include reviews for actual issues found in the changed code.
52057
52113
 
52058
52114
  Return your review as a JSON object inside a \`\`\`json block, wrapped like:
52059
52115
  <tool_attempt_completion>
52060
52116
  <tool_parameter_result>
52061
52117
  \`\`\`json
52062
52118
  {
52063
- "overview": "Summary of overall concerns.",
52119
+ "overview": "Summary of specific issues found in the diff changes, or 'No issues found' if the changes look good.",
52064
52120
  "specificReviews": [
52065
52121
  {
52066
52122
  "file": "path/filename.ext",
52067
52123
  "lines": "N or N-M",
52068
- "review": "Describe the issue and actionable fix or improvement."
52124
+ "review": "Specific issue with the changed code and exact actionable fix."
52069
52125
  }
52070
52126
  ]
52071
52127
  }
@@ -52093,14 +52149,21 @@ ${params.pullRequestDescription}
52093
52149
  parts.push(`<commit_messages>
52094
52150
  ${params.commitMessages}
52095
52151
  </commit_messages>`);
52152
+ }
52153
+ if (params.changedFiles && params.changedFiles.length > 0) {
52154
+ const fileList = params.changedFiles.map((file3) => `${file3.status}: ${file3.path}`).join(`
52155
+ `);
52156
+ parts.push(`<file_status>
52157
+ ${fileList}
52158
+ </file_status>`);
52096
52159
  }
52097
52160
  let instructions = "";
52098
52161
  if (params.commitRange) {
52099
- instructions = `Review the pull request. Get the diff using the git_diff tool with the commit range '${params.commitRange}'.`;
52162
+ instructions = `Review the pull request. Use the git_diff tool with commit range '${params.commitRange}' to inspect the actual code changes. File status information is already provided above.`;
52100
52163
  } else if (params.staged) {
52101
- instructions = "Review the staged changes. Get the diff using the git_diff tool with staged: true.";
52164
+ instructions = "Review the staged changes. Use the git_diff tool with staged: true to inspect the actual code changes. File status information is already provided above.";
52102
52165
  } else {
52103
- instructions = "Review the unstaged changes. Get the diff using the git_diff tool.";
52166
+ instructions = "Review the unstaged changes. Use the git_diff tool to inspect the actual code changes. File status information is already provided above.";
52104
52167
  }
52105
52168
  parts.push(`<review_instructions>
52106
52169
  ${instructions}
@@ -52135,6 +52198,7 @@ ${output}`,
52135
52198
  var executeTool = async (definition, ai, params, usageMeter) => {
52136
52199
  const resp = await generateText({
52137
52200
  model: ai,
52201
+ temperature: 0,
52138
52202
  system: definition.prompt,
52139
52203
  messages: [
52140
52204
  {
@@ -57496,13 +57560,16 @@ async function extendPatterns(basePatterns, dirPath) {
57496
57560
  function createIgnore(patterns) {
57497
57561
  return import_ignore.default().add(patterns);
57498
57562
  }
57499
- async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles) {
57500
- let rootPatterns = [...DEFAULT_IGNORES, ...excludeFiles || []];
57501
- try {
57502
- const rootGitignore = await fs.readFile(join2(cwd, ".gitignore"), "utf8");
57503
- const lines = rootGitignore.split(/\r?\n/).filter(Boolean);
57504
- rootPatterns = [...rootPatterns, ...lines];
57505
- } catch {}
57563
+ async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles, includeIgnored) {
57564
+ let rootPatterns = [...excludeFiles || []];
57565
+ if (!includeIgnored) {
57566
+ rootPatterns.push(...DEFAULT_IGNORES);
57567
+ try {
57568
+ const rootGitignore = await fs.readFile(join2(cwd, ".gitignore"), "utf8");
57569
+ const lines = rootGitignore.split(/\r?\n/).filter(Boolean);
57570
+ rootPatterns = [...rootPatterns, ...lines];
57571
+ } catch {}
57572
+ }
57506
57573
  const results = [];
57507
57574
  const processedDirs = new Set;
57508
57575
  const queue = [
@@ -57515,7 +57582,7 @@ async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles) {
57515
57582
  while (queue.length > 0) {
57516
57583
  const { path: currentPath, patterns: parentPatterns, relPath: currentRelPath } = queue.shift();
57517
57584
  processedDirs.add(currentRelPath);
57518
- const mergedPatterns = await extendPatterns(parentPatterns, currentPath);
57585
+ const mergedPatterns = includeIgnored ? parentPatterns : await extendPatterns(parentPatterns, currentPath);
57519
57586
  const folderIg = createIgnore(mergedPatterns);
57520
57587
  const entries = await fs.readdir(currentPath, { withFileTypes: true });
57521
57588
  entries.sort((a, b) => a.name.localeCompare(b.name));
@@ -57611,8 +57678,8 @@ async function searchFiles(path, regex, filePattern, cwd, excludeFiles) {
57611
57678
  var getProvider = (_agentName, _config, options = {}) => {
57612
57679
  const ig = import_ignore2.default().add(options.excludeFiles ?? []);
57613
57680
  const provider2 = {
57614
- readFile: async (path) => {
57615
- if (ig.ignores(path)) {
57681
+ readFile: async (path, includeIgnored) => {
57682
+ if (!includeIgnored && ig.ignores(path)) {
57616
57683
  throw new Error(`Not allow to access file ${path}`);
57617
57684
  }
57618
57685
  try {
@@ -57640,8 +57707,8 @@ var getProvider = (_agentName, _config, options = {}) => {
57640
57707
  }
57641
57708
  return await rename(sourcePath, targetPath);
57642
57709
  },
57643
- listFiles: async (path, recursive, maxCount) => {
57644
- return await listFiles(path, recursive, maxCount, process.cwd(), options.excludeFiles);
57710
+ listFiles: async (path, recursive, maxCount, includeIgnored) => {
57711
+ return await listFiles(path, recursive, maxCount, process.cwd(), options.excludeFiles, includeIgnored);
57645
57712
  },
57646
57713
  executeCommand: (command, _needApprove) => {
57647
57714
  return new Promise((resolve3, reject) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli-shared",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  "build": "bun build src/index.ts --outdir dist --target node"
18
18
  },
19
19
  "dependencies": {
20
- "@polka-codes/core": "0.9.1",
20
+ "@polka-codes/core": "0.9.4",
21
21
  "ignore": "^7.0.3",
22
22
  "lodash": "^4.17.21",
23
23
  "yaml": "^2.7.0",