@polka-codes/core 0.4.4 → 0.4.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 +195 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7951,17 +7951,169 @@ class OllamaService extends AiServiceBase {
7951
7951
  }
7952
7952
  }
7953
7953
 
7954
+ // src/AiService/OpenRouterService.ts
7955
+ class OpenRouterService extends AiServiceBase {
7956
+ #client;
7957
+ #apiKey;
7958
+ model;
7959
+ constructor(options) {
7960
+ super();
7961
+ if (!options.model) {
7962
+ throw new Error("OpenRouter requires a model");
7963
+ }
7964
+ if (!options.apiKey) {
7965
+ throw new Error("OpenRouter requires an API key");
7966
+ }
7967
+ this.#apiKey = options.apiKey;
7968
+ this.#client = new openai_default({
7969
+ baseURL: "https://openrouter.ai/api/v1",
7970
+ apiKey: options.apiKey,
7971
+ defaultHeaders: {
7972
+ "HTTP-Referer": "https://polka.codes",
7973
+ "X-Title": "Polka Codes"
7974
+ }
7975
+ });
7976
+ this.model = {
7977
+ id: options.model,
7978
+ info: {}
7979
+ };
7980
+ }
7981
+ async* send(systemPrompt, messages) {
7982
+ const openAiMessages = [
7983
+ { role: "system", content: systemPrompt },
7984
+ ...convertToOpenAiMessages(messages)
7985
+ ];
7986
+ switch (this.model.id) {
7987
+ case "anthropic/claude-3.5-sonnet":
7988
+ case "anthropic/claude-3.5-sonnet:beta":
7989
+ case "anthropic/claude-3.5-sonnet-20240620":
7990
+ case "anthropic/claude-3.5-sonnet-20240620:beta":
7991
+ case "anthropic/claude-3-5-haiku":
7992
+ case "anthropic/claude-3-5-haiku:beta":
7993
+ case "anthropic/claude-3-5-haiku-20241022":
7994
+ case "anthropic/claude-3-5-haiku-20241022:beta":
7995
+ case "anthropic/claude-3-haiku":
7996
+ case "anthropic/claude-3-haiku:beta":
7997
+ case "anthropic/claude-3-opus":
7998
+ case "anthropic/claude-3-opus:beta": {
7999
+ openAiMessages[0] = {
8000
+ role: "system",
8001
+ content: [
8002
+ {
8003
+ type: "text",
8004
+ text: systemPrompt,
8005
+ cache_control: { type: "ephemeral" }
8006
+ }
8007
+ ]
8008
+ };
8009
+ const lastTwoUserMessages = openAiMessages.filter((msg) => msg.role === "user").slice(-2);
8010
+ for (const msg of lastTwoUserMessages) {
8011
+ if (typeof msg.content === "string") {
8012
+ msg.content = [{ type: "text", text: msg.content }];
8013
+ }
8014
+ if (Array.isArray(msg.content)) {
8015
+ let lastTextPart = msg.content.filter((part) => part.type === "text").pop();
8016
+ if (!lastTextPart) {
8017
+ lastTextPart = { type: "text", text: "..." };
8018
+ msg.content.push(lastTextPart);
8019
+ }
8020
+ lastTextPart.cache_control = { type: "ephemeral" };
8021
+ }
8022
+ }
8023
+ break;
8024
+ }
8025
+ default:
8026
+ break;
8027
+ }
8028
+ let maxTokens;
8029
+ switch (this.model.id) {
8030
+ case "anthropic/claude-3.5-sonnet":
8031
+ case "anthropic/claude-3.5-sonnet:beta":
8032
+ case "anthropic/claude-3.5-sonnet-20240620":
8033
+ case "anthropic/claude-3.5-sonnet-20240620:beta":
8034
+ case "anthropic/claude-3-5-haiku":
8035
+ case "anthropic/claude-3-5-haiku:beta":
8036
+ case "anthropic/claude-3-5-haiku-20241022":
8037
+ case "anthropic/claude-3-5-haiku-20241022:beta":
8038
+ maxTokens = 8192;
8039
+ break;
8040
+ }
8041
+ let shouldApplyMiddleOutTransform = !this.model.info.supportsPromptCache;
8042
+ if (this.model.id === "deepseek/deepseek-chat") {
8043
+ shouldApplyMiddleOutTransform = true;
8044
+ }
8045
+ const stream = await this.#client.chat.completions.create({
8046
+ model: this.model.id,
8047
+ max_completion_tokens: maxTokens,
8048
+ messages: openAiMessages,
8049
+ temperature: 0,
8050
+ stream: true,
8051
+ transforms: shouldApplyMiddleOutTransform ? ["middle-out"] : undefined,
8052
+ include_reasoning: true
8053
+ });
8054
+ let genId;
8055
+ for await (const chunk of stream) {
8056
+ if ("error" in chunk) {
8057
+ const error = chunk.error;
8058
+ console.error(`OpenRouter API Error: ${error?.code} - ${error?.message}`);
8059
+ throw new Error(`OpenRouter API Error ${error?.code}: ${error?.message}`);
8060
+ }
8061
+ if (!genId && chunk.id) {
8062
+ genId = chunk.id;
8063
+ }
8064
+ const delta = chunk.choices[0]?.delta;
8065
+ if (delta?.reasoning) {
8066
+ yield {
8067
+ type: "reasoning",
8068
+ text: delta.reasoning
8069
+ };
8070
+ }
8071
+ if (delta?.content) {
8072
+ yield {
8073
+ type: "text",
8074
+ text: delta.content
8075
+ };
8076
+ }
8077
+ }
8078
+ await new Promise((resolve) => setTimeout(resolve, 1000));
8079
+ const controller = new AbortController;
8080
+ const timeout = setTimeout(() => controller.abort(), 5000);
8081
+ try {
8082
+ const response = await fetch(`https://openrouter.ai/api/v1/generation?id=${genId}`, {
8083
+ headers: {
8084
+ Authorization: `Bearer ${this.#apiKey}`
8085
+ },
8086
+ signal: controller.signal
8087
+ });
8088
+ const responseBody = await response.json();
8089
+ const generation = responseBody.data;
8090
+ yield {
8091
+ type: "usage",
8092
+ inputTokens: generation?.native_tokens_prompt || 0,
8093
+ outputTokens: generation?.native_tokens_completion || 0,
8094
+ totalCost: generation?.total_cost || 0
8095
+ };
8096
+ } catch (error) {
8097
+ console.error("Error fetching OpenRouter generation details:", error);
8098
+ } finally {
8099
+ clearTimeout(timeout);
8100
+ }
8101
+ }
8102
+ }
8103
+
7954
8104
  // src/AiService/index.ts
7955
8105
  var AiServiceProvider;
7956
8106
  ((AiServiceProvider2) => {
7957
8107
  AiServiceProvider2["Anthropic"] = "anthropic";
7958
8108
  AiServiceProvider2["Ollama"] = "ollama";
7959
8109
  AiServiceProvider2["DeepSeek"] = "deepseek";
8110
+ AiServiceProvider2["OpenRouter"] = "openrouter";
7960
8111
  })(AiServiceProvider ||= {});
7961
8112
  var defaultModels = {
7962
8113
  ["anthropic" /* Anthropic */]: "claude-3-5-sonnet-20241022",
7963
8114
  ["ollama" /* Ollama */]: "maryasov/qwen2.5-coder-cline:7b",
7964
- ["deepseek" /* DeepSeek */]: "deepseek-chat"
8115
+ ["deepseek" /* DeepSeek */]: "deepseek-chat",
8116
+ ["openrouter" /* OpenRouter */]: "anthropic/claude-3.5-sonnet"
7965
8117
  };
7966
8118
  var createService = (provider, options) => {
7967
8119
  switch (provider) {
@@ -7971,6 +8123,8 @@ var createService = (provider, options) => {
7971
8123
  return new OllamaService(options);
7972
8124
  case "deepseek" /* DeepSeek */:
7973
8125
  return new DeepSeekService(options);
8126
+ case "openrouter" /* OpenRouter */:
8127
+ return new OpenRouterService(options);
7974
8128
  }
7975
8129
  };
7976
8130
  // src/tool.ts
@@ -8278,6 +8432,9 @@ ${agents}`;
8278
8432
  callback = () => {
8279
8433
  }
8280
8434
  }) {
8435
+ if (maxIterations < 1) {
8436
+ throw new Error("Max iterations must be greater than 0");
8437
+ }
8281
8438
  const taskInfo = {
8282
8439
  options: {
8283
8440
  maxIterations
@@ -8544,6 +8701,9 @@ var getStringArray = (args, name, defaultValue) => {
8544
8701
  }
8545
8702
  return defaultValue;
8546
8703
  }
8704
+ if (ret === "") {
8705
+ return [];
8706
+ }
8547
8707
  return ret.split(",");
8548
8708
  };
8549
8709
  var getBoolean = (args, name, defaultValue) => {
@@ -9506,19 +9666,24 @@ class MultiAgent {
9506
9666
  get model() {
9507
9667
  return this.#activeAgent?.model;
9508
9668
  }
9509
- async#startTask(agentName, task, context, callback) {
9669
+ async#startTask(agentName, task, context, maxIterations, callback) {
9510
9670
  this.#activeAgent = await this.#config.createAgent(agentName);
9511
9671
  const [exitReason, info] = await this.#activeAgent.startTask({
9512
9672
  task,
9513
9673
  context,
9674
+ maxIterations,
9514
9675
  callback
9515
9676
  });
9516
9677
  if (typeof exitReason === "string") {
9517
9678
  return [exitReason, info];
9518
9679
  }
9519
9680
  if (exitReason.type === "HandOver") {
9681
+ const remainIteration = maxIterations - Math.floor(info.messages.length / 2);
9682
+ if (remainIteration < 1) {
9683
+ return ["MaxIterations", info];
9684
+ }
9520
9685
  const context2 = await this.#config.getContext(agentName, exitReason.context, exitReason.files);
9521
- const [exitReason2, info2] = await this.#startTask(exitReason.agentName, exitReason.task, context2, callback);
9686
+ const [exitReason2, info2] = await this.#startTask(exitReason.agentName, exitReason.task, context2, remainIteration, callback);
9522
9687
  info2.inputTokens += info.inputTokens;
9523
9688
  info2.outputTokens += info.outputTokens;
9524
9689
  info2.cacheWriteTokens += info.cacheWriteTokens;
@@ -9532,7 +9697,8 @@ class MultiAgent {
9532
9697
  if (this.#activeAgent) {
9533
9698
  throw new Error("An active agent already exists");
9534
9699
  }
9535
- return this.#startTask(options.agentName, options.task, options.context, options.callback);
9700
+ const maxIterations = options.maxIterations ?? 50;
9701
+ return this.#startTask(options.agentName, options.task, options.context, maxIterations, options.callback);
9536
9702
  }
9537
9703
  async continueTask(userMessage, taskInfo, callback = () => {
9538
9704
  }) {
@@ -9604,6 +9770,8 @@ ${output}`);
9604
9770
 
9605
9771
  // src/AiTool/generateGithubPullRequestDetails.ts
9606
9772
  var prompt2 = `
9773
+ # Generate Github Pull Request Details
9774
+
9607
9775
  You are given:
9608
9776
  - A branch name in <tool_input_branch_name>.
9609
9777
  - An optional context message in <tool_input_context> (which may or may not be present).
@@ -9616,10 +9784,30 @@ Your task:
9616
9784
  3. Produce a single GitHub Pull Request title.
9617
9785
  4. Produce a Pull Request description that explains the changes.
9618
9786
 
9787
+ Use the following template for the Pull Request description:
9788
+
9789
+ ---
9790
+ **Context (if provided)**:
9791
+ - Acknowledge any guiding concerns or instructions.
9792
+
9793
+ **Summary of Changes**:
9794
+ - Provide a concise list or overview of what changed.
9795
+
9796
+ **Highlights of Changed Code**:
9797
+ - Mention only the specific sections or functionalities updated, without showing full surrounding context.
9798
+
9799
+ **Additional Information (if needed)**:
9800
+ - Testing steps (if applicable).
9801
+ - Any notes or caveats.
9802
+
9803
+ ---
9804
+
9619
9805
  Output format:
9620
9806
  <tool_output>
9621
9807
  <tool_output_pr_title>YOUR PR TITLE HERE</tool_output_pr_title>
9622
- <tool_output_pr_description>YOUR PR DESCRIPTION HERE</tool_output_pr_description>
9808
+ <tool_output_pr_description>
9809
+ YOUR PR DESCRIPTION HERE
9810
+ </tool_output_pr_description>
9623
9811
  </tool_output>
9624
9812
 
9625
9813
  Below is an **example** of the input and output:
@@ -9641,7 +9829,7 @@ diff --git a/order_service.py b/order_service.py
9641
9829
  - if is_valid_order(order):
9642
9830
  - process_order(order)
9643
9831
  + validate_and_process(order)
9644
- </tool_input_commit_diff>
9832
+ </tool_input_commit_diff>
9645
9833
  </tool_input>
9646
9834
 
9647
9835
  Example Output:
@@ -9655,8 +9843,7 @@ to use the new validate_and_process method for improved maintainability.
9655
9843
 
9656
9844
  ---
9657
9845
 
9658
- Use the above format whenever you receive \`<tool_input>\` that may include a branch name, an optional context, aggregated commit messages in a single tag, and a combined diff in a single tag. Provide your final output strictly in \`<tool_output>\` with \`<tool_output_pr_title>\` and \`<tool_output_pr_description>\`.
9659
- Only highlight the changed code and avoid including the context around the changes in the description.
9846
+ Use the above format whenever you receive <tool_input> that may include a branch name, an optional context, aggregated commit messages in a single tag, and a combined diff in a single tag. Provide your final output strictly in <tool_output> with <tool_output_pr_title> and <tool_output_pr_description>. Only highlight the changed code and avoid including the context around the changes in the description.
9660
9847
  `;
9661
9848
  var generateGithubPullRequestDetails_default = {
9662
9849
  name: "generateGithubPullRequestDetails",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/core",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "license": "AGPL-3.0",
5
5
  "type": "module",
6
6
  "exports": {