@polka-codes/cli-shared 0.8.24 → 0.8.26

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 +144 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -27497,14 +27497,19 @@ import { join as join2 } from "node:path";
27497
27497
  class AiServiceBase {
27498
27498
  usageMeter;
27499
27499
  options;
27500
+ #abortController;
27500
27501
  constructor(options) {
27501
27502
  this.options = options;
27502
27503
  this.usageMeter = options.usageMeter;
27503
27504
  }
27505
+ abort() {
27506
+ this.#abortController?.abort();
27507
+ }
27504
27508
  async* send(systemPrompt, messages) {
27505
27509
  this.usageMeter.checkLimit();
27506
27510
  this.usageMeter.incrementMessageCount();
27507
- const stream = this.sendImpl(systemPrompt, messages);
27511
+ this.#abortController = new AbortController;
27512
+ const stream = this.sendImpl(systemPrompt, messages, this.#abortController.signal);
27508
27513
  for await (const chunk of stream) {
27509
27514
  switch (chunk.type) {
27510
27515
  case "usage":
@@ -27517,7 +27522,8 @@ class AiServiceBase {
27517
27522
  async request(systemPrompt, messages) {
27518
27523
  this.usageMeter.checkLimit();
27519
27524
  this.usageMeter.incrementMessageCount();
27520
- const stream = this.sendImpl(systemPrompt, messages);
27525
+ this.#abortController = new AbortController;
27526
+ const stream = this.sendImpl(systemPrompt, messages, this.#abortController.signal);
27521
27527
  const usage = {
27522
27528
  inputTokens: 0,
27523
27529
  outputTokens: 0,
@@ -31022,7 +31028,7 @@ class AnthropicService extends AiServiceBase {
31022
31028
  info: anthropicModels[id] ?? anthropicModels[anthropicDefaultModelId]
31023
31029
  };
31024
31030
  }
31025
- async* sendImpl(systemPrompt, messages) {
31031
+ async* sendImpl(systemPrompt, messages, signal) {
31026
31032
  let stream;
31027
31033
  const modelId = this.model.id;
31028
31034
  const cacheControl = this.#options.enableCache ? { type: "ephemeral" } : undefined;
@@ -31080,7 +31086,7 @@ class AnthropicService extends AiServiceBase {
31080
31086
  return message;
31081
31087
  }),
31082
31088
  stream: true
31083
- });
31089
+ }, { signal });
31084
31090
  break;
31085
31091
  }
31086
31092
  default: {
@@ -31091,7 +31097,7 @@ class AnthropicService extends AiServiceBase {
31091
31097
  system: [{ text: systemPrompt, type: "text" }],
31092
31098
  messages,
31093
31099
  stream: true
31094
- });
31100
+ }, { signal });
31095
31101
  break;
31096
31102
  }
31097
31103
  }
@@ -36449,7 +36455,7 @@ class DeepSeekService extends AiServiceBase {
36449
36455
  info: deepSeekModels[id] ?? deepSeekModels[deepSeekDefaultModelId]
36450
36456
  };
36451
36457
  }
36452
- async* sendImpl(systemPrompt, messages) {
36458
+ async* sendImpl(systemPrompt, messages, signal) {
36453
36459
  const openAiMessages = [
36454
36460
  { role: "system", content: systemPrompt },
36455
36461
  ...convertToOpenAiMessages(messages)
@@ -36461,7 +36467,7 @@ class DeepSeekService extends AiServiceBase {
36461
36467
  temperature: 0,
36462
36468
  stream: true,
36463
36469
  stream_options: { include_usage: true }
36464
- });
36470
+ }, { signal });
36465
36471
  for await (const chunk of stream) {
36466
36472
  const delta = chunk.choices[0]?.delta;
36467
36473
  if (delta?.reasoning_content) {
@@ -36505,7 +36511,7 @@ class OllamaService extends AiServiceBase {
36505
36511
  info: openAiModelInfoSaneDefaults
36506
36512
  };
36507
36513
  }
36508
- async* sendImpl(systemPrompt, messages) {
36514
+ async* sendImpl(systemPrompt, messages, signal) {
36509
36515
  const openAiMessages = [
36510
36516
  { role: "system", content: systemPrompt },
36511
36517
  ...convertToOpenAiMessages(messages)
@@ -36515,7 +36521,7 @@ class OllamaService extends AiServiceBase {
36515
36521
  messages: openAiMessages,
36516
36522
  temperature: 0,
36517
36523
  stream: true
36518
- });
36524
+ }, { signal });
36519
36525
  for await (const chunk of stream) {
36520
36526
  const delta = chunk.choices[0]?.delta;
36521
36527
  if (delta?.content) {
@@ -36562,7 +36568,7 @@ class OpenRouterService extends AiServiceBase {
36562
36568
  this.#modelProviderInfo = data.data;
36563
36569
  });
36564
36570
  }
36565
- async* sendImpl(systemPrompt, messages) {
36571
+ async* sendImpl(systemPrompt, messages, signal) {
36566
36572
  const openAiMessages = [
36567
36573
  { role: "system", content: systemPrompt },
36568
36574
  ...convertToOpenAiMessages(messages)
@@ -36622,7 +36628,7 @@ class OpenRouterService extends AiServiceBase {
36622
36628
  transforms: shouldApplyMiddleOutTransform ? ["middle-out"] : undefined,
36623
36629
  include_reasoning: true,
36624
36630
  ...reasoning
36625
- });
36631
+ }, { signal });
36626
36632
  let genId;
36627
36633
  for await (const chunk of stream) {
36628
36634
  if ("error" in chunk) {
@@ -36876,7 +36882,7 @@ var getArray = (args, name, defaultValue) => {
36876
36882
  return [ret];
36877
36883
  };
36878
36884
  // ../core/src/tools/utils/replaceInFile.ts
36879
- var replaceInFile = async (fileContent, diff) => {
36885
+ var replaceInFile = (fileContent, diff) => {
36880
36886
  const blockPattern = /<<<<<+ SEARCH>?\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
36881
36887
  const blocks = [];
36882
36888
  for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
@@ -36921,14 +36927,32 @@ var replaceInFile = async (fileContent, diff) => {
36921
36927
  const startPos = endPos - strippedSearch.length;
36922
36928
  return content.slice(0, startPos) + replace + content.slice(endPos);
36923
36929
  }
36924
- throw new Error(`Could not find the following text in file:
36925
- ${search}`);
36930
+ return null;
36926
36931
  };
36927
36932
  let updatedFile = fileContent;
36933
+ let appliedCount = 0;
36934
+ const totalCount = blocks.length;
36928
36935
  for (const { search, replace } of blocks) {
36929
- updatedFile = findAndReplace(updatedFile, search, replace);
36936
+ const result = findAndReplace(updatedFile, search, replace);
36937
+ if (result !== null) {
36938
+ updatedFile = result;
36939
+ appliedCount++;
36940
+ }
36941
+ }
36942
+ let status;
36943
+ if (appliedCount === 0) {
36944
+ status = "no_diff_applied";
36945
+ } else if (appliedCount < totalCount) {
36946
+ status = "some_diff_applied";
36947
+ } else {
36948
+ status = "all_diff_applied";
36930
36949
  }
36931
- return updatedFile;
36950
+ return {
36951
+ content: updatedFile,
36952
+ status,
36953
+ appliedCount,
36954
+ totalCount
36955
+ };
36932
36956
  };
36933
36957
  // ../core/src/tools/askFollowupQuestion.ts
36934
36958
  var toolInfo = {
@@ -37623,14 +37647,30 @@ var handler8 = async (provider, args) => {
37623
37647
  if (fileContent == null) {
37624
37648
  return {
37625
37649
  type: "Error" /* Error */,
37626
- message: `<error><replace_in_file_path>${path}</replace_in_file_path><error_message>File not found</error_message></error>`
37650
+ message: `<replace_in_file_result path="${path}" status="failed" message="File not found" />`
37651
+ };
37652
+ }
37653
+ const result = replaceInFile(fileContent, diff);
37654
+ if (result.status === "no_diff_applied") {
37655
+ return {
37656
+ type: "Error" /* Error */,
37657
+ message: `<replace_in_file_result path="${path}" status="failed" message="Unable to apply changes">
37658
+ <file_content path="${path}">${fileContent}</file_content>
37659
+ </replace_in_file_result>`
37660
+ };
37661
+ }
37662
+ await provider.writeFile(path, result.content);
37663
+ if (result.status === "some_diff_applied") {
37664
+ return {
37665
+ type: "Reply" /* Reply */,
37666
+ message: `<replace_in_file_result path="${path}" status="some_diff_applied" applied_count="${result.appliedCount}" total_count="${result.totalCount}">
37667
+ <file_content path="${path}">${result.content}</file_content>
37668
+ </replace_in_file_result>`
37627
37669
  };
37628
37670
  }
37629
- const result = await replaceInFile(fileContent, diff);
37630
- await provider.writeFile(path, result);
37631
37671
  return {
37632
37672
  type: "Reply" /* Reply */,
37633
- message: `<replace_in_file_path>${path}</replace_in_file_path>`
37673
+ message: `<replace_in_file_result path="${path}" status="all_diff_applied" />`
37634
37674
  };
37635
37675
  };
37636
37676
  var isAvailable8 = (provider) => {
@@ -38672,6 +38712,7 @@ class AgentBase {
38672
38712
  handlers;
38673
38713
  #messages = [];
38674
38714
  #policies;
38715
+ #aborted = false;
38675
38716
  constructor(name, ai, config) {
38676
38717
  this.ai = ai;
38677
38718
  if (config.agents && config.agents.length > 0) {
@@ -38703,6 +38744,10 @@ ${instance.prompt}`;
38703
38744
  this.config = config;
38704
38745
  this.#policies = policies;
38705
38746
  }
38747
+ abort() {
38748
+ this.#aborted = true;
38749
+ this.ai.abort();
38750
+ }
38706
38751
  get parameters() {
38707
38752
  return this.ai.options.parameters;
38708
38753
  }
@@ -38731,11 +38776,17 @@ ${instance.prompt}`;
38731
38776
  async#processLoop(userMessage) {
38732
38777
  let nextRequest = userMessage;
38733
38778
  while (true) {
38779
+ if (this.#aborted) {
38780
+ return { type: "Aborted" };
38781
+ }
38734
38782
  if (this.ai.usageMeter.isLimitExceeded().result) {
38735
38783
  this.#callback({ kind: "UsageExceeded" /* UsageExceeded */, agent: this });
38736
38784
  return { type: "UsageExceeded" };
38737
38785
  }
38738
38786
  const response = await this.#request(nextRequest);
38787
+ if (this.#aborted) {
38788
+ return { type: "Aborted" };
38789
+ }
38739
38790
  const resp = await this.#handleResponse(response);
38740
38791
  if (resp.type === "exit") {
38741
38792
  this.#callback({ kind: "EndTask" /* EndTask */, agent: this, exitReason: resp.reason });
@@ -38782,14 +38833,23 @@ ${instance.prompt}`;
38782
38833
  }
38783
38834
  }
38784
38835
  } catch (error) {
38836
+ if (error instanceof Error && error.name === "AbortError") {
38837
+ break;
38838
+ }
38785
38839
  console.error("Error in stream:", error);
38786
38840
  }
38787
38841
  if (currentAssistantMessage) {
38788
38842
  break;
38789
38843
  }
38844
+ if (this.#aborted) {
38845
+ break;
38846
+ }
38790
38847
  console.debug(`Retrying request ${i2 + 1} of ${retryCount}`);
38791
38848
  }
38792
38849
  if (!currentAssistantMessage) {
38850
+ if (this.#aborted) {
38851
+ return [];
38852
+ }
38793
38853
  throw new Error("No assistant message received");
38794
38854
  }
38795
38855
  this.#messages.push({
@@ -39110,6 +39170,7 @@ class MultiAgent {
39110
39170
  case "Delegate" /* Delegate */:
39111
39171
  console.warn("Unexpected exit reason", delegateResult);
39112
39172
  break;
39173
+ case "Aborted":
39113
39174
  case "Interrupted" /* Interrupted */:
39114
39175
  return delegateResult;
39115
39176
  case "Exit" /* Exit */:
@@ -39117,6 +39178,7 @@ class MultiAgent {
39117
39178
  }
39118
39179
  return delegateResult;
39119
39180
  }
39181
+ case "Aborted":
39120
39182
  case "Interrupted" /* Interrupted */:
39121
39183
  case "Exit" /* Exit */:
39122
39184
  this.#agents.pop();
@@ -39149,6 +39211,11 @@ class MultiAgent {
39149
39211
  get hasActiveAgent() {
39150
39212
  return this.#agents.length > 0;
39151
39213
  }
39214
+ abort() {
39215
+ if (this.hasActiveAgent) {
39216
+ this.#agents[this.#agents.length - 1].abort();
39217
+ }
39218
+ }
39152
39219
  }
39153
39220
  // ../core/node_modules/zod/lib/index.mjs
39154
39221
  var util;
@@ -49595,11 +49662,13 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
49595
49662
  var source_default = chalk;
49596
49663
 
49597
49664
  // src/utils/eventHandler.ts
49665
+ var toolCallStats = new Map;
49598
49666
  var printEvent = (verbose, usageMeter) => {
49599
49667
  let hadReasoning = false;
49600
49668
  return (event) => {
49601
49669
  switch (event.kind) {
49602
49670
  case "StartTask" /* StartTask */:
49671
+ toolCallStats.clear();
49603
49672
  if (verbose > 1) {
49604
49673
  console.log(`
49605
49674
  ====== System Prompt ======
@@ -49616,7 +49685,28 @@ ${event.systemPrompt}`);
49616
49685
  ======== New Request ========
49617
49686
  `);
49618
49687
  if (verbose) {
49619
- console.log(event.userMessage);
49688
+ const { userMessage } = event;
49689
+ if (typeof userMessage === "string") {
49690
+ console.log(userMessage);
49691
+ } else {
49692
+ for (const content of userMessage) {
49693
+ if (content.type === "text") {
49694
+ console.log(content.text);
49695
+ } else if (content.type === "image") {
49696
+ if (content.source.type === "base64") {
49697
+ console.log(source_default.yellow(`[Image content: ${content.source.media_type}]`));
49698
+ } else if (content.source.type === "url") {
49699
+ console.log(source_default.yellow(`[Image content from URL: ${content.source.url}]`));
49700
+ } else {
49701
+ console.log(source_default.red("[Unknown image source type]"));
49702
+ console.log(content.source);
49703
+ }
49704
+ } else {
49705
+ console.log(source_default.red("[Unknown content type]"));
49706
+ console.log(content);
49707
+ }
49708
+ }
49709
+ }
49620
49710
  console.log(`
49621
49711
 
49622
49712
  ======== Request Message Ended ========
@@ -49648,12 +49738,27 @@ ${event.systemPrompt}`);
49648
49738
  hadReasoning = true;
49649
49739
  break;
49650
49740
  case "ToolUse" /* ToolUse */:
49741
+ {
49742
+ const stats = toolCallStats.get(event.tool) ?? { calls: 0, success: 0, errors: 0 };
49743
+ stats.calls++;
49744
+ toolCallStats.set(event.tool, stats);
49745
+ }
49651
49746
  break;
49652
49747
  case "ToolReply" /* ToolReply */:
49748
+ {
49749
+ const stats = toolCallStats.get(event.tool) ?? { calls: 0, success: 0, errors: 0 };
49750
+ stats.success++;
49751
+ toolCallStats.set(event.tool, stats);
49752
+ }
49653
49753
  break;
49654
49754
  case "ToolInvalid" /* ToolInvalid */:
49655
49755
  break;
49656
49756
  case "ToolError" /* ToolError */:
49757
+ {
49758
+ const stats = toolCallStats.get(event.tool) ?? { calls: 0, success: 0, errors: 0 };
49759
+ stats.errors++;
49760
+ toolCallStats.set(event.tool, stats);
49761
+ }
49657
49762
  break;
49658
49763
  case "ToolInterrupted" /* ToolInterrupted */:
49659
49764
  break;
@@ -49699,6 +49804,24 @@ ${event.systemPrompt}`);
49699
49804
  console.log("Interrupted Message:", event.exitReason.message);
49700
49805
  break;
49701
49806
  }
49807
+ console.log(`
49808
+
49809
+ ======== Tool Call Stats ========`);
49810
+ if (toolCallStats.size > 0) {
49811
+ const tableData = [...toolCallStats.entries()].map(([tool2, stats]) => {
49812
+ const successRate = stats.calls > 0 ? stats.success / stats.calls * 100 : 0;
49813
+ return {
49814
+ "Tool Name": tool2,
49815
+ Calls: stats.calls,
49816
+ Success: stats.success,
49817
+ Errors: stats.errors,
49818
+ "Success Rate": `${successRate.toFixed(2)}%`
49819
+ };
49820
+ });
49821
+ console.table(tableData);
49822
+ } else {
49823
+ console.log("No tools were called.");
49824
+ }
49702
49825
  break;
49703
49826
  }
49704
49827
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli-shared",
3
- "version": "0.8.24",
3
+ "version": "0.8.26",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",