@polka-codes/runner 0.8.23 → 0.8.25

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 +141 -38
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -32748,7 +32748,7 @@ var {
32748
32748
  Help
32749
32749
  } = import__.default;
32750
32750
  // package.json
32751
- var version = "0.8.23";
32751
+ var version = "0.8.25";
32752
32752
 
32753
32753
  // src/runner.ts
32754
32754
  import { execSync } from "node:child_process";
@@ -32763,14 +32763,19 @@ import { join as join2 } from "node:path";
32763
32763
  class AiServiceBase {
32764
32764
  usageMeter;
32765
32765
  options;
32766
+ #abortController;
32766
32767
  constructor(options) {
32767
32768
  this.options = options;
32768
32769
  this.usageMeter = options.usageMeter;
32769
32770
  }
32771
+ abort() {
32772
+ this.#abortController?.abort();
32773
+ }
32770
32774
  async* send(systemPrompt, messages) {
32771
32775
  this.usageMeter.checkLimit();
32772
32776
  this.usageMeter.incrementMessageCount();
32773
- const stream = this.sendImpl(systemPrompt, messages);
32777
+ this.#abortController = new AbortController;
32778
+ const stream = this.sendImpl(systemPrompt, messages, this.#abortController.signal);
32774
32779
  for await (const chunk of stream) {
32775
32780
  switch (chunk.type) {
32776
32781
  case "usage":
@@ -32783,7 +32788,8 @@ class AiServiceBase {
32783
32788
  async request(systemPrompt, messages) {
32784
32789
  this.usageMeter.checkLimit();
32785
32790
  this.usageMeter.incrementMessageCount();
32786
- const stream = this.sendImpl(systemPrompt, messages);
32791
+ this.#abortController = new AbortController;
32792
+ const stream = this.sendImpl(systemPrompt, messages, this.#abortController.signal);
32787
32793
  const usage = {
32788
32794
  inputTokens: 0,
32789
32795
  outputTokens: 0,
@@ -36288,7 +36294,7 @@ class AnthropicService extends AiServiceBase {
36288
36294
  info: anthropicModels[id] ?? anthropicModels[anthropicDefaultModelId]
36289
36295
  };
36290
36296
  }
36291
- async* sendImpl(systemPrompt, messages) {
36297
+ async* sendImpl(systemPrompt, messages, signal) {
36292
36298
  let stream;
36293
36299
  const modelId = this.model.id;
36294
36300
  const cacheControl = this.#options.enableCache ? { type: "ephemeral" } : undefined;
@@ -36346,7 +36352,7 @@ class AnthropicService extends AiServiceBase {
36346
36352
  return message;
36347
36353
  }),
36348
36354
  stream: true
36349
- });
36355
+ }, { signal });
36350
36356
  break;
36351
36357
  }
36352
36358
  default: {
@@ -36357,7 +36363,7 @@ class AnthropicService extends AiServiceBase {
36357
36363
  system: [{ text: systemPrompt, type: "text" }],
36358
36364
  messages,
36359
36365
  stream: true
36360
- });
36366
+ }, { signal });
36361
36367
  break;
36362
36368
  }
36363
36369
  }
@@ -41715,7 +41721,7 @@ class DeepSeekService extends AiServiceBase {
41715
41721
  info: deepSeekModels[id] ?? deepSeekModels[deepSeekDefaultModelId]
41716
41722
  };
41717
41723
  }
41718
- async* sendImpl(systemPrompt, messages) {
41724
+ async* sendImpl(systemPrompt, messages, signal) {
41719
41725
  const openAiMessages = [
41720
41726
  { role: "system", content: systemPrompt },
41721
41727
  ...convertToOpenAiMessages(messages)
@@ -41727,7 +41733,7 @@ class DeepSeekService extends AiServiceBase {
41727
41733
  temperature: 0,
41728
41734
  stream: true,
41729
41735
  stream_options: { include_usage: true }
41730
- });
41736
+ }, { signal });
41731
41737
  for await (const chunk of stream) {
41732
41738
  const delta = chunk.choices[0]?.delta;
41733
41739
  if (delta?.reasoning_content) {
@@ -41771,7 +41777,7 @@ class OllamaService extends AiServiceBase {
41771
41777
  info: openAiModelInfoSaneDefaults
41772
41778
  };
41773
41779
  }
41774
- async* sendImpl(systemPrompt, messages) {
41780
+ async* sendImpl(systemPrompt, messages, signal) {
41775
41781
  const openAiMessages = [
41776
41782
  { role: "system", content: systemPrompt },
41777
41783
  ...convertToOpenAiMessages(messages)
@@ -41781,7 +41787,7 @@ class OllamaService extends AiServiceBase {
41781
41787
  messages: openAiMessages,
41782
41788
  temperature: 0,
41783
41789
  stream: true
41784
- });
41790
+ }, { signal });
41785
41791
  for await (const chunk of stream) {
41786
41792
  const delta = chunk.choices[0]?.delta;
41787
41793
  if (delta?.content) {
@@ -41828,7 +41834,7 @@ class OpenRouterService extends AiServiceBase {
41828
41834
  this.#modelProviderInfo = data.data;
41829
41835
  });
41830
41836
  }
41831
- async* sendImpl(systemPrompt, messages) {
41837
+ async* sendImpl(systemPrompt, messages, signal) {
41832
41838
  const openAiMessages = [
41833
41839
  { role: "system", content: systemPrompt },
41834
41840
  ...convertToOpenAiMessages(messages)
@@ -41888,7 +41894,7 @@ class OpenRouterService extends AiServiceBase {
41888
41894
  transforms: shouldApplyMiddleOutTransform ? ["middle-out"] : undefined,
41889
41895
  include_reasoning: true,
41890
41896
  ...reasoning
41891
- });
41897
+ }, { signal });
41892
41898
  let genId;
41893
41899
  for await (const chunk of stream) {
41894
41900
  if ("error" in chunk) {
@@ -42142,7 +42148,7 @@ var getArray = (args, name, defaultValue) => {
42142
42148
  return [ret];
42143
42149
  };
42144
42150
  // ../core/src/tools/utils/replaceInFile.ts
42145
- var replaceInFile = async (fileContent, diff) => {
42151
+ var replaceInFile = (fileContent, diff) => {
42146
42152
  const blockPattern = /<<<<<+ SEARCH>?\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
42147
42153
  const blocks = [];
42148
42154
  for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
@@ -42187,14 +42193,32 @@ var replaceInFile = async (fileContent, diff) => {
42187
42193
  const startPos = endPos - strippedSearch.length;
42188
42194
  return content.slice(0, startPos) + replace + content.slice(endPos);
42189
42195
  }
42190
- throw new Error(`Could not find the following text in file:
42191
- ${search}`);
42196
+ return null;
42192
42197
  };
42193
42198
  let updatedFile = fileContent;
42199
+ let appliedCount = 0;
42200
+ const totalCount = blocks.length;
42194
42201
  for (const { search, replace } of blocks) {
42195
- updatedFile = findAndReplace(updatedFile, search, replace);
42202
+ const result = findAndReplace(updatedFile, search, replace);
42203
+ if (result !== null) {
42204
+ updatedFile = result;
42205
+ appliedCount++;
42206
+ }
42207
+ }
42208
+ let status;
42209
+ if (appliedCount === 0) {
42210
+ status = "no_diff_applied";
42211
+ } else if (appliedCount < totalCount) {
42212
+ status = "some_diff_applied";
42213
+ } else {
42214
+ status = "all_diff_applied";
42196
42215
  }
42197
- return updatedFile;
42216
+ return {
42217
+ content: updatedFile,
42218
+ status,
42219
+ appliedCount,
42220
+ totalCount
42221
+ };
42198
42222
  };
42199
42223
  // ../core/src/tools/askFollowupQuestion.ts
42200
42224
  var toolInfo = {
@@ -42889,14 +42913,26 @@ var handler8 = async (provider, args) => {
42889
42913
  if (fileContent == null) {
42890
42914
  return {
42891
42915
  type: "Error" /* Error */,
42892
- message: `<error><replace_in_file_path>${path}</replace_in_file_path><error_message>File not found</error_message></error>`
42916
+ message: `<replace_in_file_result path="${path}" status="failed" message="File not found" />`
42917
+ };
42918
+ }
42919
+ const result = replaceInFile(fileContent, diff);
42920
+ if (result.status === "no_diff_applied") {
42921
+ return {
42922
+ type: "Error" /* Error */,
42923
+ message: `<replace_in_file_result path="${path}" status="failed" message="Unable to apply changes" />`
42924
+ };
42925
+ }
42926
+ await provider.writeFile(path, result.content);
42927
+ if (result.status === "some_diff_applied") {
42928
+ return {
42929
+ type: "Reply" /* Reply */,
42930
+ message: `<replace_in_file_result path="${path}" status="some_diff_applied" applied_count="${result.appliedCount}" total_count="${result.totalCount}" />`
42893
42931
  };
42894
42932
  }
42895
- const result = await replaceInFile(fileContent, diff);
42896
- await provider.writeFile(path, result);
42897
42933
  return {
42898
42934
  type: "Reply" /* Reply */,
42899
- message: `<replace_in_file_path>${path}</replace_in_file_path>`
42935
+ message: `<replace_in_file_result path="${path}" status="all_diff_applied" />`
42900
42936
  };
42901
42937
  };
42902
42938
  var isAvailable8 = (provider) => {
@@ -43287,7 +43323,7 @@ var updateKnowledge_default = {
43287
43323
  // ../core/src/tools/writeToFile.ts
43288
43324
  var toolInfo11 = {
43289
43325
  name: "write_to_file",
43290
- 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;`.",
43326
+ 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;`, `&gt;`, or `&amp;`. Also ensure there is no unwanted CDATA tags in the content.",
43291
43327
  parameters: [
43292
43328
  {
43293
43329
  name: "path",
@@ -43338,7 +43374,10 @@ var handler11 = async (provider, args) => {
43338
43374
  };
43339
43375
  }
43340
43376
  const path = getString(args, "path");
43341
- const content = getString(args, "content");
43377
+ let content = getString(args, "content");
43378
+ const trimmedContent = content.trim();
43379
+ if (trimmedContent.startsWith("<![CDATA[") && content.endsWith("]]>"))
43380
+ content = trimmedContent.slice(9, -3);
43342
43381
  await provider.writeFile(path, content);
43343
43382
  return {
43344
43383
  type: "Reply" /* Reply */,
@@ -43897,12 +43936,27 @@ Ensure the opening and closing tags are correctly nested and closed, and that yo
43897
43936
  Avoid unnecessary text or symbols before or after the tool use.
43898
43937
  Avoid unnecessary escape characters or special characters.
43899
43938
  `,
43900
- toolResults: (tool, result) => `<tool_response>
43901
- <tool_name>${tool}</tool_name>
43902
- <tool_result>
43903
- ${result}
43904
- </tool_result>
43905
- </tool_response>`,
43939
+ toolResults: (tool, result) => {
43940
+ if (typeof result === "string") {
43941
+ return [
43942
+ {
43943
+ type: "text",
43944
+ text: `<tool_response name=${tool}>${result}</tool_response>`
43945
+ }
43946
+ ];
43947
+ }
43948
+ return [
43949
+ {
43950
+ type: "text",
43951
+ text: `<tool_response name=${tool}>`
43952
+ },
43953
+ ...result,
43954
+ {
43955
+ type: "text",
43956
+ text: "</tool_response>"
43957
+ }
43958
+ ];
43959
+ },
43906
43960
  commandResult: (command, exitCode, stdout, stderr) => `<command>${command}</command>
43907
43961
  <command_exit_code>${exitCode}</command_exit_code>
43908
43962
  <command_stdout>
@@ -43920,6 +43974,7 @@ class AgentBase {
43920
43974
  handlers;
43921
43975
  #messages = [];
43922
43976
  #policies;
43977
+ #aborted = false;
43923
43978
  constructor(name, ai, config) {
43924
43979
  this.ai = ai;
43925
43980
  if (config.agents && config.agents.length > 0) {
@@ -43951,6 +44006,10 @@ ${instance.prompt}`;
43951
44006
  this.config = config;
43952
44007
  this.#policies = policies;
43953
44008
  }
44009
+ abort() {
44010
+ this.#aborted = true;
44011
+ this.ai.abort();
44012
+ }
43954
44013
  get parameters() {
43955
44014
  return this.ai.options.parameters;
43956
44015
  }
@@ -43979,11 +44038,17 @@ ${instance.prompt}`;
43979
44038
  async#processLoop(userMessage) {
43980
44039
  let nextRequest = userMessage;
43981
44040
  while (true) {
44041
+ if (this.#aborted) {
44042
+ return { type: "Aborted" };
44043
+ }
43982
44044
  if (this.ai.usageMeter.isLimitExceeded().result) {
43983
44045
  this.#callback({ kind: "UsageExceeded" /* UsageExceeded */, agent: this });
43984
44046
  return { type: "UsageExceeded" };
43985
44047
  }
43986
44048
  const response = await this.#request(nextRequest);
44049
+ if (this.#aborted) {
44050
+ return { type: "Aborted" };
44051
+ }
43987
44052
  const resp = await this.#handleResponse(response);
43988
44053
  if (resp.type === "exit") {
43989
44054
  this.#callback({ kind: "EndTask" /* EndTask */, agent: this, exitReason: resp.reason });
@@ -44030,14 +44095,23 @@ ${instance.prompt}`;
44030
44095
  }
44031
44096
  }
44032
44097
  } catch (error) {
44098
+ if (error instanceof Error && error.name === "AbortError") {
44099
+ break;
44100
+ }
44033
44101
  console.error("Error in stream:", error);
44034
44102
  }
44035
44103
  if (currentAssistantMessage) {
44036
44104
  break;
44037
44105
  }
44106
+ if (this.#aborted) {
44107
+ break;
44108
+ }
44038
44109
  console.debug(`Retrying request ${i2 + 1} of ${retryCount}`);
44039
44110
  }
44040
44111
  if (!currentAssistantMessage) {
44112
+ if (this.#aborted) {
44113
+ return [];
44114
+ }
44041
44115
  throw new Error("No assistant message received");
44042
44116
  }
44043
44117
  this.#messages.push({
@@ -44066,23 +44140,26 @@ ${instance.prompt}`;
44066
44140
  await this.#callback({ kind: "ToolUse" /* ToolUse */, agent: this, tool: content.name });
44067
44141
  const toolResp = await this.#invokeTool(content.name, content.params);
44068
44142
  switch (toolResp.type) {
44069
- case "Reply" /* Reply */:
44143
+ case "Reply" /* Reply */: {
44070
44144
  await this.#callback({ kind: "ToolReply" /* ToolReply */, agent: this, tool: content.name });
44071
44145
  toolResponses.push({ type: "response", tool: content.name, response: toolResp.message });
44072
44146
  break;
44147
+ }
44073
44148
  case "Exit" /* Exit */:
44074
44149
  if (toolResponses.length > 0) {
44075
44150
  break outer;
44076
44151
  }
44077
44152
  return { type: "exit", reason: toolResp };
44078
- case "Invalid" /* Invalid */:
44153
+ case "Invalid" /* Invalid */: {
44079
44154
  await this.#callback({ kind: "ToolInvalid" /* ToolInvalid */, agent: this, tool: content.name });
44080
44155
  toolResponses.push({ type: "response", tool: content.name, response: toolResp.message });
44081
44156
  break outer;
44082
- case "Error" /* Error */:
44157
+ }
44158
+ case "Error" /* Error */: {
44083
44159
  await this.#callback({ kind: "ToolError" /* ToolError */, agent: this, tool: content.name });
44084
44160
  toolResponses.push({ type: "response", tool: content.name, response: toolResp.message });
44085
44161
  break outer;
44162
+ }
44086
44163
  case "Interrupted" /* Interrupted */:
44087
44164
  await this.#callback({ kind: "ToolInterrupted" /* ToolInterrupted */, agent: this, tool: content.name });
44088
44165
  return { type: "exit", reason: toolResp };
@@ -44132,9 +44209,7 @@ ${instance.prompt}`;
44132
44209
  if (toolResponses.length === 0) {
44133
44210
  return { type: "reply", message: responsePrompts.requireUseTool };
44134
44211
  }
44135
- const finalResp = toolResponses.filter((resp) => resp.type === "response").map(({ tool, response: response2 }) => responsePrompts.toolResults(tool, response2)).join(`
44136
-
44137
- `);
44212
+ const finalResp = toolResponses.filter((resp) => resp.type === "response").flatMap(({ tool, response: response2 }) => responsePrompts.toolResults(tool, response2));
44138
44213
  return { type: "reply", message: finalResp };
44139
44214
  }
44140
44215
  async#invokeTool(name, args) {
@@ -44357,6 +44432,7 @@ class MultiAgent {
44357
44432
  case "Delegate" /* Delegate */:
44358
44433
  console.warn("Unexpected exit reason", delegateResult);
44359
44434
  break;
44435
+ case "Aborted":
44360
44436
  case "Interrupted" /* Interrupted */:
44361
44437
  return delegateResult;
44362
44438
  case "Exit" /* Exit */:
@@ -44364,6 +44440,7 @@ class MultiAgent {
44364
44440
  }
44365
44441
  return delegateResult;
44366
44442
  }
44443
+ case "Aborted":
44367
44444
  case "Interrupted" /* Interrupted */:
44368
44445
  case "Exit" /* Exit */:
44369
44446
  this.#agents.pop();
@@ -44396,6 +44473,11 @@ class MultiAgent {
44396
44473
  get hasActiveAgent() {
44397
44474
  return this.#agents.length > 0;
44398
44475
  }
44476
+ abort() {
44477
+ if (this.hasActiveAgent) {
44478
+ this.#agents[this.#agents.length - 1].abort();
44479
+ }
44480
+ }
44399
44481
  }
44400
44482
  // ../core/node_modules/zod/lib/index.mjs
44401
44483
  var util;
@@ -54344,6 +54426,8 @@ var getProvider = (agentName, config2, options = {}) => {
54344
54426
  }
54345
54427
  return provider2;
54346
54428
  };
54429
+ // ../cli-shared/src/utils/eventHandler.ts
54430
+ var toolCallStats = new Map;
54347
54431
  // ../../node_modules/ws/wrapper.mjs
54348
54432
  var import_stream = __toESM(require_stream(), 1);
54349
54433
  var import_receiver = __toESM(require_receiver(), 1);
@@ -58371,6 +58455,25 @@ var wsIncomingMessageSchema = z3.discriminatedUnion("type", [
58371
58455
  z3.object({ type: z3.literal("get_files") }),
58372
58456
  z3.object({ type: z3.literal("done") })
58373
58457
  ]);
58458
+ var textBlockParamSchema = z3.object({
58459
+ type: z3.literal("text"),
58460
+ text: z3.string()
58461
+ });
58462
+ var imageBlockParamSchema = z3.object({
58463
+ type: z3.literal("image"),
58464
+ source: z3.union([
58465
+ z3.object({
58466
+ data: z3.string(),
58467
+ media_type: z3.string(),
58468
+ type: z3.literal("base64")
58469
+ }),
58470
+ z3.object({
58471
+ type: z3.literal("url"),
58472
+ url: z3.string()
58473
+ })
58474
+ ])
58475
+ });
58476
+ var userContentSchema = z3.union([z3.string(), z3.array(z3.union([textBlockParamSchema, imageBlockParamSchema]))]);
58374
58477
  var wsOutgoingMessageSchema = z3.discriminatedUnion("type", [
58375
58478
  z3.object({
58376
58479
  type: z3.literal("pending_tools_response"),
@@ -58378,7 +58481,7 @@ var wsOutgoingMessageSchema = z3.discriminatedUnion("type", [
58378
58481
  responses: z3.array(z3.object({
58379
58482
  index: z3.number(),
58380
58483
  tool: z3.string(),
58381
- response: z3.string()
58484
+ response: userContentSchema
58382
58485
  }))
58383
58486
  }),
58384
58487
  z3.object({
@@ -58653,7 +58756,7 @@ class Runner {
58653
58756
  }
58654
58757
  };
58655
58758
  const respMsg = await fn();
58656
- if (typeof respMsg === "string") {
58759
+ if (typeof respMsg === "string" || Array.isArray(respMsg)) {
58657
58760
  responses.push({
58658
58761
  index: request.index,
58659
58762
  tool: request.tool,
@@ -58769,7 +58872,7 @@ class Runner {
58769
58872
  path,
58770
58873
  content
58771
58874
  });
58772
- console.log(`Sent content for file: ${path}`);
58875
+ console.log(`Sent content for file: ${path}, size: ${content.length}`);
58773
58876
  } else {
58774
58877
  console.error(`Path is not a file or directory: ${path}`);
58775
58878
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/runner",
3
- "version": "0.8.23",
3
+ "version": "0.8.25",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",