@polka-codes/runner 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 +111 -44
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -21008,7 +21008,7 @@ var {
21008
21008
  Help
21009
21009
  } = import__.default;
21010
21010
  // package.json
21011
- var version = "0.9.3";
21011
+ var version = "0.9.5";
21012
21012
 
21013
21013
  // src/runner.ts
21014
21014
  import { execSync } from "node:child_process";
@@ -32488,7 +32488,17 @@ var toolInfo7 = {
32488
32488
  return true;
32489
32489
  }
32490
32490
  return val;
32491
- }, 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)" })
32491
+ }, 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)" }),
32492
+ includeIgnored: exports_external.preprocess((val) => {
32493
+ if (typeof val === "string") {
32494
+ const lower = val.toLowerCase();
32495
+ if (lower === "false")
32496
+ return false;
32497
+ if (lower === "true")
32498
+ return true;
32499
+ }
32500
+ return val;
32501
+ }, 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)" })
32492
32502
  }).meta({
32493
32503
  examples: [
32494
32504
  {
@@ -32509,8 +32519,8 @@ var handler7 = async (provider, args) => {
32509
32519
  message: "Not possible to list files. Abort."
32510
32520
  };
32511
32521
  }
32512
- const { path, maxCount, recursive } = toolInfo7.parameters.parse(args);
32513
- const [files, limitReached] = await provider.listFiles(path, recursive, maxCount);
32522
+ const { path, maxCount, recursive, includeIgnored } = toolInfo7.parameters.parse(args);
32523
+ const [files, limitReached] = await provider.listFiles(path, recursive, maxCount, includeIgnored);
32514
32524
  return {
32515
32525
  type: "Reply" /* Reply */,
32516
32526
  message: `<list_files_path>${path}</list_files_path>
@@ -32539,7 +32549,17 @@ var toolInfo8 = {
32539
32549
  return [];
32540
32550
  const values = Array.isArray(val) ? val : [val];
32541
32551
  return values.flatMap((i) => typeof i === "string" ? i.split(",") : []).filter((s) => s.length > 0);
32542
- }, exports_external.array(exports_external.string())).describe("The path of the file to read").meta({ usageValue: "Comma separated paths here" })
32552
+ }, exports_external.array(exports_external.string())).describe("The path of the file to read").meta({ usageValue: "Comma separated paths here" }),
32553
+ includeIgnored: exports_external.preprocess((val) => {
32554
+ if (typeof val === "string") {
32555
+ const lower = val.toLowerCase();
32556
+ if (lower === "false")
32557
+ return false;
32558
+ if (lower === "true")
32559
+ return true;
32560
+ }
32561
+ return val;
32562
+ }, 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)" })
32543
32563
  }).meta({
32544
32564
  examples: [
32545
32565
  {
@@ -32565,10 +32585,10 @@ var handler8 = async (provider, args) => {
32565
32585
  message: "Not possible to read file. Abort."
32566
32586
  };
32567
32587
  }
32568
- const { path: paths } = toolInfo8.parameters.parse(args);
32588
+ const { path: paths, includeIgnored } = toolInfo8.parameters.parse(args);
32569
32589
  const resp = [];
32570
32590
  for (const path of paths) {
32571
- const fileContent = await provider.readFile(path);
32591
+ const fileContent = await provider.readFile(path, includeIgnored);
32572
32592
  if (!fileContent) {
32573
32593
  resp.push(`<read_file_file_content path="${path}" file_not_found="true" />`);
32574
32594
  } else {
@@ -32878,7 +32898,7 @@ var handler11 = async (provider, args) => {
32878
32898
  }
32879
32899
  try {
32880
32900
  const { path, diff } = toolInfo11.parameters.parse(args);
32881
- const fileContent = await provider.readFile(path);
32901
+ const fileContent = await provider.readFile(path, false);
32882
32902
  if (fileContent == null) {
32883
32903
  return {
32884
32904
  type: "Error" /* Error */,
@@ -56300,23 +56320,30 @@ ${instance.prompt}`;
56300
56320
  const requestTimeoutSeconds = this.config.requestTimeoutSeconds ?? 90;
56301
56321
  let respMessages = [];
56302
56322
  for (let i = 0;i < retryCount; i++) {
56323
+ if (this.#aborted) {
56324
+ break;
56325
+ }
56303
56326
  respMessages = [];
56304
56327
  let timeout;
56328
+ let requestAbortController;
56329
+ requestAbortController = new AbortController;
56330
+ this.#abortController = requestAbortController;
56305
56331
  const resetTimeout = () => {
56306
56332
  if (timeout) {
56307
56333
  clearTimeout(timeout);
56308
56334
  }
56309
- if (requestTimeoutSeconds > 0) {
56335
+ if (requestTimeoutSeconds > 0 && requestAbortController) {
56310
56336
  timeout = setTimeout(() => {
56311
- console.debug(`No data received for ${requestTimeoutSeconds} seconds. Aborting request.`);
56312
- this.abort();
56337
+ console.debug(`Request timeout after ${requestTimeoutSeconds} seconds. Canceling current request attempt ${i + 1}/${retryCount}.`);
56338
+ requestAbortController?.abort();
56313
56339
  }, requestTimeoutSeconds * 1000);
56314
56340
  }
56315
56341
  };
56316
- this.#abortController = new AbortController;
56317
56342
  try {
56343
+ resetTimeout();
56318
56344
  const streamTextOptions = {
56319
56345
  model: this.ai,
56346
+ temperature: 0,
56320
56347
  messages,
56321
56348
  providerOptions: this.config.parameters?.providerOptions,
56322
56349
  onChunk: async ({ chunk }) => {
@@ -56336,7 +56363,7 @@ ${instance.prompt}`;
56336
56363
  onError: async (error81) => {
56337
56364
  console.error("Error in stream:", error81);
56338
56365
  },
56339
- abortSignal: this.#abortController.signal
56366
+ abortSignal: requestAbortController.signal
56340
56367
  };
56341
56368
  if (this.config.toolFormat === "native") {
56342
56369
  streamTextOptions.tools = this.#toolSet;
@@ -56349,11 +56376,19 @@ ${instance.prompt}`;
56349
56376
  });
56350
56377
  const resp = await stream.response;
56351
56378
  respMessages = resp.messages;
56379
+ if (timeout) {
56380
+ clearTimeout(timeout);
56381
+ timeout = undefined;
56382
+ }
56352
56383
  } catch (error81) {
56353
56384
  if (error81 instanceof Error && error81.name === "AbortError") {
56354
- break;
56385
+ if (this.#aborted) {
56386
+ break;
56387
+ }
56388
+ console.debug(`Request attempt ${i + 1} timed out, will retry`);
56389
+ } else {
56390
+ console.error("Error in stream:", error81);
56355
56391
  }
56356
- console.error("Error in stream:", error81);
56357
56392
  } finally {
56358
56393
  if (timeout) {
56359
56394
  clearTimeout(timeout);
@@ -56365,16 +56400,26 @@ ${instance.prompt}`;
56365
56400
  if (this.#aborted) {
56366
56401
  break;
56367
56402
  }
56368
- console.debug(`Retrying request ${i + 1} of ${retryCount}`);
56403
+ if (i < retryCount - 1) {
56404
+ console.debug(`Retrying request ${i + 2} of ${retryCount}`);
56405
+ }
56369
56406
  }
56370
56407
  if (respMessages.length === 0) {
56371
56408
  if (this.#aborted) {
56372
56409
  return [];
56373
56410
  }
56374
- throw new Error("No assistant message received");
56411
+ throw new Error("No assistant message received after all retry attempts");
56375
56412
  }
56376
56413
  this.#messages.push(...respMessages);
56377
56414
  if (this.config.toolFormat === "native") {
56415
+ const assistantText = respMessages.map((msg) => {
56416
+ if (typeof msg.content === "string") {
56417
+ return msg.content;
56418
+ }
56419
+ return msg.content.map((part) => part.type === "text" || part.type === "reasoning" ? part.text : "").join("");
56420
+ }).join(`
56421
+ `);
56422
+ await this.#callback({ kind: "EndRequest" /* EndRequest */, agent: this, message: assistantText });
56378
56423
  return respMessages.flatMap((msg) => {
56379
56424
  if (msg.role === "assistant") {
56380
56425
  const content = msg.content;
@@ -56382,7 +56427,7 @@ ${instance.prompt}`;
56382
56427
  return [{ type: "text", content }];
56383
56428
  }
56384
56429
  return content.flatMap((part) => {
56385
- if (part.type === "text") {
56430
+ if (part.type === "text" || part.type === "reasoning") {
56386
56431
  return [{ type: "text", content: part.text }];
56387
56432
  }
56388
56433
  if (part.type === "tool-call") {
@@ -57338,37 +57383,48 @@ var prompt5 = `
57338
57383
 
57339
57384
  You are a senior software engineer reviewing code changes.
57340
57385
 
57386
+ ## Critical Instructions
57387
+ **ONLY review the actual changes shown in the diff.** Do not comment on existing code that wasn't modified.
57388
+
57341
57389
  ## Viewing Changes
57342
- - Use **git_diff** to inspect code.
57343
- - **Pull request**: use the provided commit range.
57344
- - **Local changes**: diff staged or unstaged files.
57390
+ - **Use git_diff** to inspect the actual code changes for each relevant file.
57391
+ - **Pull request**: use the provided commit range for the git_diff tool.
57392
+ - **Local changes**: diff staged or unstaged files using the git_diff tool.
57345
57393
  - If a pull request is present you may receive:
57346
57394
  - <pr_title>
57347
57395
  - <pr_description>
57348
57396
  - <commit_messages>
57349
57397
  - A <review_instructions> tag tells you the focus of the review.
57398
+ - File status information is provided in <file_status> - use this to understand which files were modified, added, deleted, or renamed.
57399
+
57400
+ ## Review Guidelines
57401
+ Focus exclusively on the changed lines (+ additions, - deletions, modified lines):
57402
+ - **Specific issues**: Point to exact problems in the changed code with line references
57403
+ - **Actionable fixes**: Provide concrete solutions, not vague suggestions
57404
+ - **Clear reasoning**: Explain why each issue matters and how to fix it
57405
+ - **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
57350
57406
 
57351
- ## Focus Areas
57352
- - Readability and maintainability
57353
- - Correctness, edge cases, potential bugs
57354
- - Performance implications
57355
- - Clarity of intent
57356
- - Best-practice adherence
57407
+ ## What NOT to review
57408
+ - Existing unchanged code
57409
+ - Overall project structure or architecture (unless directly impacted by changes)
57410
+ - Generic best practices unrelated to the specific changes
57411
+ - Missing features or functionality not part of this diff
57357
57412
 
57358
57413
  ## Output Format
57359
57414
  Do **not** include praise or positive feedback. Ignore generated files such as lock files.
57415
+ Only include reviews for actual issues found in the changed code.
57360
57416
 
57361
57417
  Return your review as a JSON object inside a \`\`\`json block, wrapped like:
57362
57418
  <tool_attempt_completion>
57363
57419
  <tool_parameter_result>
57364
57420
  \`\`\`json
57365
57421
  {
57366
- "overview": "Summary of overall concerns.",
57422
+ "overview": "Summary of specific issues found in the diff changes, or 'No issues found' if the changes look good.",
57367
57423
  "specificReviews": [
57368
57424
  {
57369
57425
  "file": "path/filename.ext",
57370
57426
  "lines": "N or N-M",
57371
- "review": "Describe the issue and actionable fix or improvement."
57427
+ "review": "Specific issue with the changed code and exact actionable fix."
57372
57428
  }
57373
57429
  ]
57374
57430
  }
@@ -57396,14 +57452,21 @@ ${params.pullRequestDescription}
57396
57452
  parts.push(`<commit_messages>
57397
57453
  ${params.commitMessages}
57398
57454
  </commit_messages>`);
57455
+ }
57456
+ if (params.changedFiles && params.changedFiles.length > 0) {
57457
+ const fileList = params.changedFiles.map((file3) => `${file3.status}: ${file3.path}`).join(`
57458
+ `);
57459
+ parts.push(`<file_status>
57460
+ ${fileList}
57461
+ </file_status>`);
57399
57462
  }
57400
57463
  let instructions = "";
57401
57464
  if (params.commitRange) {
57402
- instructions = `Review the pull request. Get the diff using the git_diff tool with the commit range '${params.commitRange}'.`;
57465
+ 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.`;
57403
57466
  } else if (params.staged) {
57404
- instructions = "Review the staged changes. Get the diff using the git_diff tool with staged: true.";
57467
+ 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.";
57405
57468
  } else {
57406
- instructions = "Review the unstaged changes. Get the diff using the git_diff tool.";
57469
+ instructions = "Review the unstaged changes. Use the git_diff tool to inspect the actual code changes. File status information is already provided above.";
57407
57470
  }
57408
57471
  parts.push(`<review_instructions>
57409
57472
  ${instructions}
@@ -57438,6 +57501,7 @@ ${output}`,
57438
57501
  var executeTool = async (definition, ai, params, usageMeter) => {
57439
57502
  const resp = await generateText({
57440
57503
  model: ai,
57504
+ temperature: 0,
57441
57505
  system: definition.prompt,
57442
57506
  messages: [
57443
57507
  {
@@ -62785,13 +62849,16 @@ async function extendPatterns(basePatterns, dirPath) {
62785
62849
  function createIgnore(patterns) {
62786
62850
  return import_ignore.default().add(patterns);
62787
62851
  }
62788
- async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles) {
62789
- let rootPatterns = [...DEFAULT_IGNORES, ...excludeFiles || []];
62790
- try {
62791
- const rootGitignore = await fs.readFile(join2(cwd, ".gitignore"), "utf8");
62792
- const lines = rootGitignore.split(/\r?\n/).filter(Boolean);
62793
- rootPatterns = [...rootPatterns, ...lines];
62794
- } catch {}
62852
+ async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles, includeIgnored) {
62853
+ let rootPatterns = [...excludeFiles || []];
62854
+ if (!includeIgnored) {
62855
+ rootPatterns.push(...DEFAULT_IGNORES);
62856
+ try {
62857
+ const rootGitignore = await fs.readFile(join2(cwd, ".gitignore"), "utf8");
62858
+ const lines = rootGitignore.split(/\r?\n/).filter(Boolean);
62859
+ rootPatterns = [...rootPatterns, ...lines];
62860
+ } catch {}
62861
+ }
62795
62862
  const results = [];
62796
62863
  const processedDirs = new Set;
62797
62864
  const queue = [
@@ -62804,7 +62871,7 @@ async function listFiles(dirPath, recursive, maxCount, cwd, excludeFiles) {
62804
62871
  while (queue.length > 0) {
62805
62872
  const { path: currentPath, patterns: parentPatterns, relPath: currentRelPath } = queue.shift();
62806
62873
  processedDirs.add(currentRelPath);
62807
- const mergedPatterns = await extendPatterns(parentPatterns, currentPath);
62874
+ const mergedPatterns = includeIgnored ? parentPatterns : await extendPatterns(parentPatterns, currentPath);
62808
62875
  const folderIg = createIgnore(mergedPatterns);
62809
62876
  const entries = await fs.readdir(currentPath, { withFileTypes: true });
62810
62877
  entries.sort((a, b) => a.name.localeCompare(b.name));
@@ -62900,8 +62967,8 @@ async function searchFiles(path, regex, filePattern, cwd, excludeFiles) {
62900
62967
  var getProvider = (_agentName, _config, options = {}) => {
62901
62968
  const ig = import_ignore2.default().add(options.excludeFiles ?? []);
62902
62969
  const provider2 = {
62903
- readFile: async (path) => {
62904
- if (ig.ignores(path)) {
62970
+ readFile: async (path, includeIgnored) => {
62971
+ if (!includeIgnored && ig.ignores(path)) {
62905
62972
  throw new Error(`Not allow to access file ${path}`);
62906
62973
  }
62907
62974
  try {
@@ -62929,8 +62996,8 @@ var getProvider = (_agentName, _config, options = {}) => {
62929
62996
  }
62930
62997
  return await rename(sourcePath, targetPath);
62931
62998
  },
62932
- listFiles: async (path, recursive, maxCount) => {
62933
- return await listFiles(path, recursive, maxCount, process.cwd(), options.excludeFiles);
62999
+ listFiles: async (path, recursive, maxCount, includeIgnored) => {
63000
+ return await listFiles(path, recursive, maxCount, process.cwd(), options.excludeFiles, includeIgnored);
62934
63001
  },
62935
63002
  executeCommand: (command, _needApprove) => {
62936
63003
  return new Promise((resolve3, reject) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/runner",
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,8 +17,8 @@
17
17
  "build": "bun build src/index.ts --outdir dist --target node"
18
18
  },
19
19
  "dependencies": {
20
- "@polka-codes/cli-shared": "0.9.1",
21
- "@polka-codes/core": "0.9.1",
20
+ "@polka-codes/cli-shared": "0.9.4",
21
+ "@polka-codes/core": "0.9.4",
22
22
  "commander": "^13.0.0",
23
23
  "dotenv": "^16.4.7",
24
24
  "ignore": "^7.0.3",