bare-agent 0.2.2 → 0.3.0

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.
package/index.js CHANGED
@@ -17,6 +17,7 @@ const {
17
17
  TimeoutError,
18
18
  ValidationError,
19
19
  CircuitOpenError,
20
+ MaxRoundsError,
20
21
  } = require('./src/errors');
21
22
 
22
23
  module.exports = {
@@ -36,4 +37,5 @@ module.exports = {
36
37
  TimeoutError,
37
38
  ValidationError,
38
39
  CircuitOpenError,
40
+ MaxRoundsError,
39
41
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-agent",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "files": [
5
5
  "index.js",
6
6
  "src/",
package/src/errors.js CHANGED
@@ -43,6 +43,12 @@ class CircuitOpenError extends BareAgentError {
43
43
  }
44
44
  }
45
45
 
46
+ class MaxRoundsError extends BareAgentError {
47
+ constructor(message, opts = {}) {
48
+ super(message || 'Loop exceeded maximum rounds', { code: 'MAX_ROUNDS', retryable: false, ...opts });
49
+ }
50
+ }
51
+
46
52
  module.exports = {
47
53
  BareAgentError,
48
54
  ProviderError,
@@ -50,4 +56,5 @@ module.exports = {
50
56
  TimeoutError,
51
57
  ValidationError,
52
58
  CircuitOpenError,
59
+ MaxRoundsError,
53
60
  };
package/src/loop.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { ToolError } = require('./errors');
3
+ const { ToolError, MaxRoundsError } = require('./errors');
4
4
 
5
5
  class Loop {
6
6
  /**
@@ -25,6 +25,7 @@ class Loop {
25
25
  this.onToolCall = options.onToolCall || null;
26
26
  this.onText = options.onText || null;
27
27
  this.onError = options.onError || null;
28
+ this.throwOnError = options.throwOnError !== undefined ? options.throwOnError : true;
28
29
  this.store = options.store || null;
29
30
  this._stopped = false;
30
31
  this._history = []; // for chat() stateful mode
@@ -78,6 +79,7 @@ class Loop {
78
79
  } catch (err) {
79
80
  this.stream?.emit({ type: 'loop:error', data: { error: err.message, round } });
80
81
  this.onError?.(err);
82
+ if (this.throwOnError) throw err;
81
83
  return { text: '', toolCalls: [], usage: lastUsage, error: err.message };
82
84
  }
83
85
 
@@ -148,6 +150,7 @@ class Loop {
148
150
  // maxRounds exceeded
149
151
  const warning = `[Loop] ended after ${this.maxRounds} rounds without final response`;
150
152
  this.stream?.emit({ type: 'loop:done', data: { text: '', warning } });
153
+ if (this.throwOnError) throw new MaxRoundsError(warning);
151
154
  return { text: '', toolCalls: [], usage: lastUsage, error: warning };
152
155
  }
153
156
 
package/src/planner.js CHANGED
@@ -25,6 +25,8 @@ class Planner {
25
25
  if (!options.provider) throw new Error('[Planner] requires a provider');
26
26
  this.provider = options.provider;
27
27
  this.prompt = options.prompt || PLAN_PROMPT;
28
+ this._cacheTTL = options.cacheTTL || 0;
29
+ this._cache = new Map();
28
30
  }
29
31
 
30
32
  /**
@@ -37,6 +39,14 @@ class Planner {
37
39
  * @throws {Error} `[Planner] step missing id or action` — when a step lacks required fields.
38
40
  */
39
41
  async plan(goal, context = {}) {
42
+ if (this._cacheTTL > 0) {
43
+ const cacheKey = goal + '|' + (context.info || '');
44
+ const cached = this._cache.get(cacheKey);
45
+ if (cached && Date.now() < cached.expiresAt) {
46
+ return cached.result;
47
+ }
48
+ }
49
+
40
50
  const messages = [
41
51
  { role: 'system', content: this.prompt },
42
52
  ];
@@ -50,7 +60,18 @@ class Planner {
50
60
  temperature: 0,
51
61
  });
52
62
 
53
- return this._parse(result.text);
63
+ const steps = this._parse(result.text);
64
+
65
+ if (this._cacheTTL > 0) {
66
+ const cacheKey = goal + '|' + (context.info || '');
67
+ this._cache.set(cacheKey, { result: steps, expiresAt: Date.now() + this._cacheTTL });
68
+ }
69
+
70
+ return steps;
71
+ }
72
+
73
+ clearCache() {
74
+ this._cache.clear();
54
75
  }
55
76
 
56
77
  _parse(text) {
@@ -23,6 +23,7 @@ class CLIPipeProvider {
23
23
  this.env = options.env || undefined;
24
24
  this.timeout = options.timeout ?? 30000;
25
25
  this.systemPromptFlag = options.systemPromptFlag || null;
26
+ this.onChunk = options.onChunk || null;
26
27
  }
27
28
 
28
29
  /**
@@ -88,7 +89,7 @@ class CLIPipeProvider {
88
89
  let stderr = '';
89
90
  let killed = false;
90
91
 
91
- child.stdout.on('data', d => { stdout += d; });
92
+ child.stdout.on('data', d => { stdout += d; this.onChunk?.(d.toString()); });
92
93
  child.stderr.on('data', d => { stderr += d; });
93
94
 
94
95
  child.on('error', err => {