@sprucelabs/sprucebot-llm 16.0.0 → 17.0.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.
@@ -11,7 +11,7 @@
11
11
  "error"
12
12
  ],
13
13
  "regressionproof": {
14
- "enabled": false,
14
+ "enabled": true,
15
15
  "projectName": "sprucebot-llm"
16
16
  }
17
17
  }
@@ -1,7 +1,7 @@
1
1
  import { Schema } from '@sprucelabs/schema';
2
2
  import { Log } from '@sprucelabs/spruce-skill-utils';
3
3
  import Anthropic from '@anthropic-ai/sdk';
4
- import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort } from '../../llm.types';
4
+ import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort, LmmTokenUsage } from '../../llm.types';
5
5
  export default class AnthropicAdapter implements LlmAdapter {
6
6
  static Class?: new (apiKey: string, options?: AnthropicAdapterOptions) => LlmAdapter;
7
7
  static Anthropic: typeof Anthropic;
@@ -12,6 +12,7 @@ export default class AnthropicAdapter implements LlmAdapter {
12
12
  private memoryLimit?;
13
13
  private isThinkingEnabled;
14
14
  private log?;
15
+ private usage;
15
16
  private constructor();
16
17
  static Adapter(apiKey: string, options: AnthropicAdapterOptions): LlmAdapter;
17
18
  sendMessage(bot: SprucebotLlmBot<Schema>, options?: SendMessageOptions): Promise<string>;
@@ -19,6 +20,7 @@ export default class AnthropicAdapter implements LlmAdapter {
19
20
  setModel(model: string): void;
20
21
  setReasoningEffort(effort: LllmReasoningEffort): void;
21
22
  setMemoryLimit(limit: number): void;
23
+ getTokenUsage(): LmmTokenUsage;
22
24
  }
23
25
  export interface AnthropicAdapterOptions {
24
26
  log?: Log;
@@ -10,6 +10,13 @@ class AnthropicAdapter {
10
10
  constructor(apiKey, options) {
11
11
  this.model = 'claude-sonnet-4-5';
12
12
  this.isThinkingEnabled = false;
13
+ this.usage = {
14
+ inputTokens: 0,
15
+ outputTokens: 0,
16
+ totalTokens: 0,
17
+ cacheCreationTokens: 0,
18
+ cacheReadTokens: 0,
19
+ };
13
20
  (0, schema_1.assertOptions)({ apiKey, maxTokens: options?.maxTokens }, [
14
21
  'apiKey',
15
22
  'maxTokens',
@@ -68,6 +75,17 @@ class AnthropicAdapter {
68
75
  }, sendOptions);
69
76
  const { usage } = response;
70
77
  this.log?.info(`[TOKEN USAGE] input=${usage.input_tokens} cache_create=${usage.cache_creation_input_tokens ?? 0} cache_read=${usage.cache_read_input_tokens ?? 0} output=${usage.output_tokens}`);
78
+ this.usage = {
79
+ inputTokens: this.usage.inputTokens + usage.input_tokens,
80
+ outputTokens: this.usage.outputTokens + usage.output_tokens,
81
+ totalTokens: this.usage.totalTokens +
82
+ usage.input_tokens +
83
+ usage.output_tokens,
84
+ cacheCreationTokens: (this.usage.cacheCreationTokens ?? 0) +
85
+ (usage.cache_creation_input_tokens ?? 0),
86
+ cacheReadTokens: (this.usage.cacheReadTokens ?? 0) +
87
+ (usage.cache_read_input_tokens ?? 0),
88
+ };
71
89
  const text = response.content
72
90
  .filter((block) => block.type === 'text')
73
91
  ?.map((block) => block.text)
@@ -84,6 +102,9 @@ class AnthropicAdapter {
84
102
  setMemoryLimit(limit) {
85
103
  this.memoryLimit = limit;
86
104
  }
105
+ getTokenUsage() {
106
+ return this.usage;
107
+ }
87
108
  }
88
109
  AnthropicAdapter.Anthropic = sdk_1.default;
89
110
  exports.default = AnthropicAdapter;
@@ -1,6 +1,6 @@
1
1
  import { Schema } from '@sprucelabs/schema';
2
2
  import { Log } from '@sprucelabs/spruce-skill-utils';
3
- import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort } from '../../llm.types';
3
+ import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort, LmmTokenUsage } from '../../llm.types';
4
4
  export default class OllamaAdapter implements LlmAdapter {
5
5
  static Class?: new (apiKey: string, options?: OllamaAdapterOptions) => LlmAdapter;
6
6
  private openai;
@@ -11,6 +11,7 @@ export default class OllamaAdapter implements LlmAdapter {
11
11
  setModel(model: string): void;
12
12
  setReasoningEffort(effort: LllmReasoningEffort): void;
13
13
  setMemoryLimit(_limit: number): void;
14
+ getTokenUsage(): LmmTokenUsage;
14
15
  }
15
16
  export interface OllamaAdapterOptions {
16
17
  log?: Log;
@@ -28,5 +28,12 @@ class OllamaAdapter {
28
28
  setMemoryLimit(_limit) {
29
29
  throw new Error('Method not implemented.');
30
30
  }
31
+ getTokenUsage() {
32
+ return {
33
+ inputTokens: 0,
34
+ outputTokens: 0,
35
+ totalTokens: 0,
36
+ };
37
+ }
31
38
  }
32
39
  exports.default = OllamaAdapter;
@@ -1,7 +1,7 @@
1
1
  import { Log } from '@sprucelabs/spruce-skill-utils';
2
2
  import OpenAI from 'openai';
3
3
  import { ReasoningEffort } from 'openai/resources';
4
- import { LlmAdapter, SendMessageOptions, SprucebotLlmBot } from '../../llm.types';
4
+ import { LlmAdapter, LmmTokenUsage, SendMessageOptions, SprucebotLlmBot } from '../../llm.types';
5
5
  export default class OpenAiAdapter implements LlmAdapter {
6
6
  static Class?: new (apiKey: string, options?: OpenAiAdapterOptions) => LlmAdapter;
7
7
  static OpenAI: typeof OpenAI;
@@ -18,6 +18,7 @@ export default class OpenAiAdapter implements LlmAdapter {
18
18
  setModel(model: string): void;
19
19
  setMemoryLimit(limit: number): void;
20
20
  setReasoningEffort(effort: ReasoningEffort): void;
21
+ getTokenUsage(): LmmTokenUsage;
21
22
  }
22
23
  export declare const MESSAGE_RESPONSE_ERROR_MESSAGE = "Oh no! Something went wrong and I can't talk right now!";
23
24
  export interface OpenAiAdapterOptions {
@@ -48,6 +48,13 @@ class OpenAiAdapter {
48
48
  setReasoningEffort(effort) {
49
49
  this.reasoningEffort = effort;
50
50
  }
51
+ getTokenUsage() {
52
+ return {
53
+ inputTokens: 0,
54
+ outputTokens: 0,
55
+ totalTokens: 0,
56
+ };
57
+ }
51
58
  }
52
59
  OpenAiAdapter.OpenAI = openai_1.default;
53
60
  exports.default = OpenAiAdapter;
@@ -1,7 +1,7 @@
1
1
  import { Schema } from '@sprucelabs/schema';
2
2
  import { Log } from '@sprucelabs/spruce-skill-utils';
3
3
  import Anthropic from '@anthropic-ai/sdk';
4
- import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort } from '../../llm.types';
4
+ import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort, LmmTokenUsage } from '../../llm.types';
5
5
  export default class AnthropicAdapter implements LlmAdapter {
6
6
  static Class?: new (apiKey: string, options?: AnthropicAdapterOptions) => LlmAdapter;
7
7
  static Anthropic: typeof Anthropic;
@@ -12,6 +12,7 @@ export default class AnthropicAdapter implements LlmAdapter {
12
12
  private memoryLimit?;
13
13
  private isThinkingEnabled;
14
14
  private log?;
15
+ private usage;
15
16
  private constructor();
16
17
  static Adapter(apiKey: string, options: AnthropicAdapterOptions): LlmAdapter;
17
18
  sendMessage(bot: SprucebotLlmBot<Schema>, options?: SendMessageOptions): Promise<string>;
@@ -19,6 +20,7 @@ export default class AnthropicAdapter implements LlmAdapter {
19
20
  setModel(model: string): void;
20
21
  setReasoningEffort(effort: LllmReasoningEffort): void;
21
22
  setMemoryLimit(limit: number): void;
23
+ getTokenUsage(): LmmTokenUsage;
22
24
  }
23
25
  export interface AnthropicAdapterOptions {
24
26
  log?: Log;
@@ -14,6 +14,13 @@ class AnthropicAdapter {
14
14
  constructor(apiKey, options) {
15
15
  this.model = 'claude-sonnet-4-5';
16
16
  this.isThinkingEnabled = false;
17
+ this.usage = {
18
+ inputTokens: 0,
19
+ outputTokens: 0,
20
+ totalTokens: 0,
21
+ cacheCreationTokens: 0,
22
+ cacheReadTokens: 0,
23
+ };
17
24
  assertOptions({ apiKey, maxTokens: options === null || options === void 0 ? void 0 : options.maxTokens }, [
18
25
  'apiKey',
19
26
  'maxTokens',
@@ -39,7 +46,7 @@ class AnthropicAdapter {
39
46
  }
40
47
  sendHandler(params, sendOptions) {
41
48
  return __awaiter(this, void 0, void 0, function* () {
42
- var _a, _b, _c, _d;
49
+ var _a, _b, _c, _d, _e, _f, _g, _h;
43
50
  const { messages: openAiMessages, model } = params;
44
51
  const messages = [];
45
52
  const cacheMarkerIdx = openAiMessages.findIndex((msg) => msg.cache_marker);
@@ -73,8 +80,19 @@ class AnthropicAdapter {
73
80
  }, sendOptions);
74
81
  const { usage } = response;
75
82
  (_a = this.log) === null || _a === void 0 ? void 0 : _a.info(`[TOKEN USAGE] input=${usage.input_tokens} cache_create=${(_b = usage.cache_creation_input_tokens) !== null && _b !== void 0 ? _b : 0} cache_read=${(_c = usage.cache_read_input_tokens) !== null && _c !== void 0 ? _c : 0} output=${usage.output_tokens}`);
76
- const text = (_d = response.content
77
- .filter((block) => block.type === 'text')) === null || _d === void 0 ? void 0 : _d.map((block) => block.text).join('').trim();
83
+ this.usage = {
84
+ inputTokens: this.usage.inputTokens + usage.input_tokens,
85
+ outputTokens: this.usage.outputTokens + usage.output_tokens,
86
+ totalTokens: this.usage.totalTokens +
87
+ usage.input_tokens +
88
+ usage.output_tokens,
89
+ cacheCreationTokens: ((_d = this.usage.cacheCreationTokens) !== null && _d !== void 0 ? _d : 0) +
90
+ ((_e = usage.cache_creation_input_tokens) !== null && _e !== void 0 ? _e : 0),
91
+ cacheReadTokens: ((_f = this.usage.cacheReadTokens) !== null && _f !== void 0 ? _f : 0) +
92
+ ((_g = usage.cache_read_input_tokens) !== null && _g !== void 0 ? _g : 0),
93
+ };
94
+ const text = (_h = response.content
95
+ .filter((block) => block.type === 'text')) === null || _h === void 0 ? void 0 : _h.map((block) => block.text).join('').trim();
78
96
  return text;
79
97
  });
80
98
  }
@@ -87,6 +105,9 @@ class AnthropicAdapter {
87
105
  setMemoryLimit(limit) {
88
106
  this.memoryLimit = limit;
89
107
  }
108
+ getTokenUsage() {
109
+ return this.usage;
110
+ }
90
111
  }
91
112
  AnthropicAdapter.Anthropic = Anthropic;
92
113
  export default AnthropicAdapter;
@@ -1,6 +1,6 @@
1
1
  import { Schema } from '@sprucelabs/schema';
2
2
  import { Log } from '@sprucelabs/spruce-skill-utils';
3
- import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort } from '../../llm.types';
3
+ import { LlmAdapter, SprucebotLlmBot, SendMessageOptions, LllmReasoningEffort, LmmTokenUsage } from '../../llm.types';
4
4
  export default class OllamaAdapter implements LlmAdapter {
5
5
  static Class?: new (apiKey: string, options?: OllamaAdapterOptions) => LlmAdapter;
6
6
  private openai;
@@ -11,6 +11,7 @@ export default class OllamaAdapter implements LlmAdapter {
11
11
  setModel(model: string): void;
12
12
  setReasoningEffort(effort: LllmReasoningEffort): void;
13
13
  setMemoryLimit(_limit: number): void;
14
+ getTokenUsage(): LmmTokenUsage;
14
15
  }
15
16
  export interface OllamaAdapterOptions {
16
17
  log?: Log;
@@ -33,4 +33,11 @@ export default class OllamaAdapter {
33
33
  setMemoryLimit(_limit) {
34
34
  throw new Error('Method not implemented.');
35
35
  }
36
+ getTokenUsage() {
37
+ return {
38
+ inputTokens: 0,
39
+ outputTokens: 0,
40
+ totalTokens: 0,
41
+ };
42
+ }
36
43
  }
@@ -1,7 +1,7 @@
1
1
  import { Log } from '@sprucelabs/spruce-skill-utils';
2
2
  import OpenAI from 'openai';
3
3
  import { ReasoningEffort } from 'openai/resources';
4
- import { LlmAdapter, SendMessageOptions, SprucebotLlmBot } from '../../llm.types';
4
+ import { LlmAdapter, LmmTokenUsage, SendMessageOptions, SprucebotLlmBot } from '../../llm.types';
5
5
  export default class OpenAiAdapter implements LlmAdapter {
6
6
  static Class?: new (apiKey: string, options?: OpenAiAdapterOptions) => LlmAdapter;
7
7
  static OpenAI: typeof OpenAI;
@@ -18,6 +18,7 @@ export default class OpenAiAdapter implements LlmAdapter {
18
18
  setModel(model: string): void;
19
19
  setMemoryLimit(limit: number): void;
20
20
  setReasoningEffort(effort: ReasoningEffort): void;
21
+ getTokenUsage(): LmmTokenUsage;
21
22
  }
22
23
  export declare const MESSAGE_RESPONSE_ERROR_MESSAGE = "Oh no! Something went wrong and I can't talk right now!";
23
24
  export interface OpenAiAdapterOptions {
@@ -53,6 +53,13 @@ class OpenAiAdapter {
53
53
  setReasoningEffort(effort) {
54
54
  this.reasoningEffort = effort;
55
55
  }
56
+ getTokenUsage() {
57
+ return {
58
+ inputTokens: 0,
59
+ outputTokens: 0,
60
+ totalTokens: 0,
61
+ };
62
+ }
56
63
  }
57
64
  OpenAiAdapter.OpenAI = OpenAI;
58
65
  export default OpenAiAdapter;
@@ -21,6 +21,14 @@ export interface LlmAdapter {
21
21
  setModel(model: string): void;
22
22
  setReasoningEffort(effort: LllmReasoningEffort): void;
23
23
  setMemoryLimit(limit: number): void;
24
+ getTokenUsage(): LmmTokenUsage;
25
+ }
26
+ export interface LmmTokenUsage {
27
+ inputTokens: number;
28
+ outputTokens: number;
29
+ totalTokens: number;
30
+ cacheCreationTokens?: number;
31
+ cacheReadTokens?: number;
24
32
  }
25
33
  export interface PromptOptions<StateSchema extends Schema, State extends SchemaValues<StateSchema> = SchemaValues<StateSchema>> {
26
34
  /**
@@ -1,5 +1,5 @@
1
1
  import { OpenAiAdapterOptions } from '../bots/adapters/OpenAiAdapter';
2
- import { LllmReasoningEffort, LlmAdapter, SendMessageOptions, SprucebotLlmBot } from '../llm.types';
2
+ import { LllmReasoningEffort, LlmAdapter, LmmTokenUsage, SendMessageOptions, SprucebotLlmBot } from '../llm.types';
3
3
  export default class SpyLlmAdapter implements LlmAdapter {
4
4
  static instance: SpyLlmAdapter;
5
5
  lastSendMessageBot?: SprucebotLlmBot;
@@ -16,4 +16,5 @@ export default class SpyLlmAdapter implements LlmAdapter {
16
16
  setModel(model: string): void;
17
17
  setReasoningEffort(_effort: LllmReasoningEffort): void;
18
18
  setMemoryLimit(_limit: number): void;
19
+ getTokenUsage(): LmmTokenUsage;
19
20
  }
@@ -34,4 +34,11 @@ export default class SpyLlmAdapter {
34
34
  }
35
35
  setReasoningEffort(_effort) { }
36
36
  setMemoryLimit(_limit) { }
37
+ getTokenUsage() {
38
+ return {
39
+ inputTokens: 0,
40
+ outputTokens: 0,
41
+ totalTokens: 0,
42
+ };
43
+ }
37
44
  }
@@ -21,6 +21,14 @@ export interface LlmAdapter {
21
21
  setModel(model: string): void;
22
22
  setReasoningEffort(effort: LllmReasoningEffort): void;
23
23
  setMemoryLimit(limit: number): void;
24
+ getTokenUsage(): LmmTokenUsage;
25
+ }
26
+ export interface LmmTokenUsage {
27
+ inputTokens: number;
28
+ outputTokens: number;
29
+ totalTokens: number;
30
+ cacheCreationTokens?: number;
31
+ cacheReadTokens?: number;
24
32
  }
25
33
  export interface PromptOptions<StateSchema extends Schema, State extends SchemaValues<StateSchema> = SchemaValues<StateSchema>> {
26
34
  /**
@@ -1,5 +1,5 @@
1
1
  import { OpenAiAdapterOptions } from '../bots/adapters/OpenAiAdapter';
2
- import { LllmReasoningEffort, LlmAdapter, SendMessageOptions, SprucebotLlmBot } from '../llm.types';
2
+ import { LllmReasoningEffort, LlmAdapter, LmmTokenUsage, SendMessageOptions, SprucebotLlmBot } from '../llm.types';
3
3
  export default class SpyLlmAdapter implements LlmAdapter {
4
4
  static instance: SpyLlmAdapter;
5
5
  lastSendMessageBot?: SprucebotLlmBot;
@@ -16,4 +16,5 @@ export default class SpyLlmAdapter implements LlmAdapter {
16
16
  setModel(model: string): void;
17
17
  setReasoningEffort(_effort: LllmReasoningEffort): void;
18
18
  setMemoryLimit(_limit: number): void;
19
+ getTokenUsage(): LmmTokenUsage;
19
20
  }
@@ -25,5 +25,12 @@ class SpyLlmAdapter {
25
25
  }
26
26
  setReasoningEffort(_effort) { }
27
27
  setMemoryLimit(_limit) { }
28
+ getTokenUsage() {
29
+ return {
30
+ inputTokens: 0,
31
+ outputTokens: 0,
32
+ totalTokens: 0,
33
+ };
34
+ }
28
35
  }
29
36
  exports.default = SpyLlmAdapter;
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "eta"
9
9
  ]
10
10
  },
11
- "version": "16.0.0",
11
+ "version": "17.0.0",
12
12
  "files": [
13
13
  "build"
14
14
  ],
@@ -65,14 +65,14 @@
65
65
  "chat.images": "node ./build/chatWithImages.js"
66
66
  },
67
67
  "dependencies": {
68
- "@anthropic-ai/sdk": "^0.78.0",
69
- "@sprucelabs/error": "^8.1.14",
70
- "@sprucelabs/mercury-event-emitter": "^46.1.13",
71
- "@sprucelabs/mercury-types": "^49.1.15",
72
- "@sprucelabs/schema": "^34.0.2",
73
- "@sprucelabs/spruce-skill-utils": "^34.0.21",
68
+ "@anthropic-ai/sdk": "^0.86.1",
69
+ "@sprucelabs/error": "^8.1.16",
70
+ "@sprucelabs/mercury-event-emitter": "^46.1.19",
71
+ "@sprucelabs/mercury-types": "^49.1.20",
72
+ "@sprucelabs/schema": "^34.0.7",
73
+ "@sprucelabs/spruce-skill-utils": "^34.0.26",
74
74
  "eta": "3.5.0",
75
- "openai": "^6.27.0"
75
+ "openai": "^6.34.0"
76
76
  },
77
77
  "resolutions": {
78
78
  "eta": "3.5.0"
@@ -80,23 +80,23 @@
80
80
  "devDependencies": {
81
81
  "@regressionproof/cli": "^0.9.4",
82
82
  "@regressionproof/jest-reporter": "^0.9.4",
83
- "@sprucelabs/esm-postbuild": "^9.0.23",
84
- "@sprucelabs/jest-json-reporter": "^10.0.31",
85
- "@sprucelabs/resolve-path-aliases": "^4.0.22",
83
+ "@sprucelabs/esm-postbuild": "^9.0.26",
84
+ "@sprucelabs/jest-json-reporter": "^10.0.33",
85
+ "@sprucelabs/resolve-path-aliases": "^4.0.26",
86
86
  "@sprucelabs/semantic-release": "^6.0.0",
87
- "@sprucelabs/test": "^11.1.6",
88
- "@sprucelabs/test-utils": "^7.2.17",
89
- "@types/node": "^25.5.0",
87
+ "@sprucelabs/test": "^11.1.7",
88
+ "@sprucelabs/test-utils": "^7.2.20",
89
+ "@types/node": "^25.5.2",
90
90
  "chokidar-cli": "^3.0.0",
91
- "dotenv": "^17.3.1",
92
- "eslint": "^10.0.3",
91
+ "dotenv": "^17.4.1",
92
+ "eslint": "^10.2.0",
93
93
  "eslint-config-spruce": "^11.2.35",
94
94
  "jest": "^30.3.0",
95
95
  "jest-circus": "^30.3.0",
96
96
  "prettier": "^3.8.1",
97
97
  "ts-node": "^10.9.2",
98
98
  "tsc-watch": "^7.2.0",
99
- "typescript": "^5.9.3"
99
+ "typescript": "^6.0.2"
100
100
  },
101
101
  "jest": {
102
102
  "testRunner": "jest-circus/runner",