@polka-codes/core 0.9.28 → 0.9.30

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.
@@ -343,6 +343,14 @@ export { commandStepSpecHandler as commandStepSpecHandler_alias_1 }
343
343
  export { commandStepSpecHandler as commandStepSpecHandler_alias_2 }
344
344
  export { commandStepSpecHandler as commandStepSpecHandler_alias_3 }
345
345
 
346
+ /**
347
+ * Utility to compute exponential backoff delays for rate-limit handling. generated by polka.codes
348
+ *
349
+ * The backoff starts at baseSeconds and doubles each time, capped at capSeconds.
350
+ * Example with base=2, cap=60: 2, 4, 8, 16, 32, 60, 60, ...
351
+ */
352
+ export declare function computeRateLimitBackoffSeconds(count: number, baseSeconds?: number, capSeconds?: number): number;
353
+
346
354
  declare type Config = z.infer<typeof configSchema>;
347
355
  export { Config }
348
356
  export { Config as Config_alias_1 }
@@ -1985,6 +1993,7 @@ declare type WorkflowContext = {
1985
1993
  parameters: Record<string, any>;
1986
1994
  verbose?: number;
1987
1995
  agentCallback?: TaskEventCallback;
1996
+ logger?: Console;
1988
1997
  };
1989
1998
  export { WorkflowContext }
1990
1999
  export { WorkflowContext as WorkflowContext_alias_1 }
package/dist/index.js CHANGED
@@ -1433,6 +1433,21 @@ function toToolInfoV1(tool) {
1433
1433
  return v1Tool;
1434
1434
  }
1435
1435
 
1436
+ // src/Agent/backoff.ts
1437
+ function computeRateLimitBackoffSeconds(count, baseSeconds = 2, capSeconds = 60) {
1438
+ if (!Number.isFinite(count) || count <= 0) {
1439
+ count = 1;
1440
+ }
1441
+ if (!Number.isFinite(baseSeconds) || baseSeconds <= 0) {
1442
+ baseSeconds = 2;
1443
+ }
1444
+ if (!Number.isFinite(capSeconds) || capSeconds <= 0) {
1445
+ capSeconds = 60;
1446
+ }
1447
+ const delay = baseSeconds * 2 ** (count - 1);
1448
+ return Math.min(delay, capSeconds);
1449
+ }
1450
+
1436
1451
  // src/Agent/parseAssistantMessage.ts
1437
1452
  function parseNestedParameters(content, parameterPrefix, childrenParams) {
1438
1453
  const result = {};
@@ -2011,6 +2026,7 @@ ${instance.prompt}`;
2011
2026
  const retryCount = this.config.retryCount ?? 5;
2012
2027
  const requestTimeoutSeconds = this.config.requestTimeoutSeconds ?? 90;
2013
2028
  let respMessages = [];
2029
+ let rateLimitErrorCount = 0;
2014
2030
  for (let i = 0; i < retryCount; i++) {
2015
2031
  if (this.#aborted) {
2016
2032
  break;
@@ -2026,7 +2042,7 @@ ${instance.prompt}`;
2026
2042
  }
2027
2043
  if (requestTimeoutSeconds > 0 && requestAbortController) {
2028
2044
  timeout = setTimeout(() => {
2029
- console.debug(
2045
+ console.error(
2030
2046
  `
2031
2047
  Request timeout after ${requestTimeoutSeconds} seconds. Canceling current request attempt ${i + 1}/${retryCount}.`
2032
2048
  );
@@ -2071,6 +2087,7 @@ Request timeout after ${requestTimeoutSeconds} seconds. Canceling current reques
2071
2087
  });
2072
2088
  const resp = await stream.response;
2073
2089
  respMessages = resp.messages;
2090
+ rateLimitErrorCount = 0;
2074
2091
  if (timeout) {
2075
2092
  clearTimeout(timeout);
2076
2093
  timeout = void 0;
@@ -2080,8 +2097,19 @@ Request timeout after ${requestTimeoutSeconds} seconds. Canceling current reques
2080
2097
  if (this.#aborted) {
2081
2098
  break;
2082
2099
  }
2083
- console.debug(`Request attempt ${i + 1} timed out, will retry`);
2100
+ console.error(`Request attempt ${i + 1} timed out, will retry`);
2101
+ } else if (error?.error?.error?.code === "rate_limit_exceeded" || error?.error?.code === "rate_limit_exceeded" || error?.code === "rate_limit_exceeded" || error?.status === 429 || error?.error?.status === 429) {
2102
+ rateLimitErrorCount++;
2103
+ const waitSeconds = computeRateLimitBackoffSeconds(rateLimitErrorCount);
2104
+ console.error(`Rate limit exceeded. Waiting ${waitSeconds}s before retrying...`);
2105
+ if (timeout) {
2106
+ clearTimeout(timeout);
2107
+ timeout = void 0;
2108
+ }
2109
+ await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1e3));
2110
+ console.error("Retrying request...");
2084
2111
  } else {
2112
+ rateLimitErrorCount = 0;
2085
2113
  console.error("Error in stream:", error);
2086
2114
  }
2087
2115
  } finally {
@@ -2110,7 +2138,7 @@ Request timeout after ${requestTimeoutSeconds} seconds. Canceling current reques
2110
2138
  break;
2111
2139
  }
2112
2140
  if (i < retryCount - 1) {
2113
- console.debug(`
2141
+ console.error(`
2114
2142
  Retrying request ${i + 2} of ${retryCount}`);
2115
2143
  }
2116
2144
  }
@@ -3760,8 +3788,9 @@ var makeAgentStepSpecHandler = (getModelFn) => ({
3760
3788
  return {
3761
3789
  ...step2,
3762
3790
  async run(input, context, resumedState) {
3791
+ const logger = context.logger ?? console;
3763
3792
  if (context.verbose && context.verbose >= 1) {
3764
- console.log(`[agent-step] Running agent step '${step2.id}' with input:`, input);
3793
+ logger.log(`[agent-step] Running agent step '${step2.id}' with input:`, input);
3765
3794
  }
3766
3795
  try {
3767
3796
  const model = await getModelFn(step2, context);
@@ -3783,9 +3812,9 @@ var makeAgentStepSpecHandler = (getModelFn) => ({
3783
3812
  throw new Error(`Unknown agent: ${agentName}`);
3784
3813
  }
3785
3814
  if (context.verbose && context.verbose >= 1) {
3786
- console.log(`[agent-step] Using agent: ${agentName}`);
3815
+ logger.log(`[agent-step] Using agent: ${agentName}`);
3787
3816
  }
3788
- const agentOptions = {
3817
+ return new AgentClass({
3789
3818
  ai: model,
3790
3819
  os: parameters.os ?? "linux",
3791
3820
  provider: context.provider,
@@ -3795,15 +3824,15 @@ var makeAgentStepSpecHandler = (getModelFn) => ({
3795
3824
  usageMeter,
3796
3825
  parameters: modelParameters,
3797
3826
  scripts: parameters.scripts,
3798
- callback: context.agentCallback
3799
- };
3800
- return new AgentClass(agentOptions);
3827
+ callback: context.agentCallback,
3828
+ requireToolUse: false
3829
+ });
3801
3830
  } else {
3802
3831
  if (!step2.systemPrompt) {
3803
3832
  throw new Error("No system prompt specified for the agent step.");
3804
3833
  }
3805
3834
  if (context.verbose && context.verbose >= 1) {
3806
- console.log(`[agent-step] Using generic WorkflowAgent`);
3835
+ logger.log(`[agent-step] Using generic WorkflowAgent`);
3807
3836
  }
3808
3837
  const systemPrompt = resolveTemplatedString(step2.systemPrompt, input);
3809
3838
  return new WorkflowAgent("agent", model, {
@@ -3818,7 +3847,7 @@ var makeAgentStepSpecHandler = (getModelFn) => ({
3818
3847
  toolFormat,
3819
3848
  parameters: modelParameters,
3820
3849
  usageMeter,
3821
- requireToolUse: true
3850
+ requireToolUse: false
3822
3851
  });
3823
3852
  }
3824
3853
  };
@@ -3841,11 +3870,11 @@ var makeAgentStepSpecHandler = (getModelFn) => ({
3841
3870
  }
3842
3871
  }
3843
3872
  if (context.verbose && context.verbose >= 1) {
3844
- console.log(`[agent-step] Starting agent with content:`, JSON.stringify(combinedContentParts, null, 2));
3873
+ logger.log(`[agent-step] Starting agent with content:`, JSON.stringify(combinedContentParts, null, 2));
3845
3874
  }
3846
3875
  const exitReason = await agent.start(combinedContentParts);
3847
3876
  if (context.verbose && context.verbose >= 1) {
3848
- console.log(`[agent-step] Agent exited with reason:`, exitReason);
3877
+ logger.log(`[agent-step] Agent exited with reason:`, exitReason);
3849
3878
  }
3850
3879
  const handleExitReason = (reason) => {
3851
3880
  switch (reason.type) {
@@ -4012,15 +4041,16 @@ var command = (id, ...command2) => ({
4012
4041
 
4013
4042
  // src/workflow/runStep.ts
4014
4043
  var runStep = async (step2, input, context, resumedState, allOutputs) => {
4044
+ const logger = context.logger ?? console;
4015
4045
  if (context.verbose && context.verbose >= 1) {
4016
- console.log(`[workflow] running step: ${step2.id}`);
4017
- console.log(`[workflow] input: ${JSON.stringify(input, null, 2)}`);
4046
+ logger.log(`[workflow] running step: ${step2.id}`);
4047
+ logger.log(`[workflow] input: ${JSON.stringify(input, null, 2)}`);
4018
4048
  }
4019
4049
  try {
4020
4050
  const validatedInput = step2.inputSchema?.parse(input) ?? input;
4021
4051
  const result = await step2.run({ ...validatedInput, $: allOutputs }, context, resumedState);
4022
4052
  if (context.verbose && context.verbose >= 1) {
4023
- console.log(`[workflow] step result: ${step2.id}`, JSON.stringify(result, null, 2));
4053
+ logger.log(`[workflow] step result: ${step2.id}`, JSON.stringify(result, null, 2));
4024
4054
  }
4025
4055
  if (result.type === "success") {
4026
4056
  const validatedOutput = step2.outputSchema?.parse(result.output) ?? result.output;
@@ -4032,7 +4062,7 @@ var runStep = async (step2, input, context, resumedState, allOutputs) => {
4032
4062
  return result;
4033
4063
  } catch (error) {
4034
4064
  if (context.verbose && context.verbose >= 1) {
4035
- console.error(`[workflow] step error: ${step2.id}`, error);
4065
+ logger.error(`[workflow] step error: ${step2.id}`, error);
4036
4066
  }
4037
4067
  return { type: "error", error };
4038
4068
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/core",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",