the-token-company 0.3.0 → 0.3.2

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/dist/anthropic.js CHANGED
@@ -31,9 +31,9 @@ function hasSearchToolUse(response) {
31
31
  function formatSearchResults(results) {
32
32
  return results.map(r => `Source: ${r.title}\nURL: ${r.url}\n${r.content}`).join("\n\n");
33
33
  }
34
- async function handleSearchLoop(response, params, originalCreate, ttcClient, rest) {
34
+ async function handleSearchLoop(response, params, originalCreate, ttcClient, stats, rest) {
35
+ const messages = [...(params.messages || [])];
35
36
  while (hasSearchToolUse(response)) {
36
- const messages = [...(params.messages || [])];
37
37
  // Add assistant response
38
38
  const assistantContent = response.content.map((b) => {
39
39
  if (typeof b.toJSON === 'function')
@@ -47,6 +47,7 @@ async function handleSearchLoop(response, params, originalCreate, ttcClient, res
47
47
  if (block.type === "tool_use" && block.name === "ttc_web_search") {
48
48
  const query = block.input?.query || "";
49
49
  const searchResult = await ttcClient.search(query);
50
+ stats._recordSearch(searchResult);
50
51
  toolResults.push({
51
52
  type: "tool_result",
52
53
  tool_use_id: block.id,
@@ -101,7 +102,10 @@ export function withCompression(client, options) {
101
102
  if (params?.messages) {
102
103
  params = {
103
104
  ...params,
104
- messages: await compressAnthropicMessages(compressor, params.messages, model, roleAggr, { stripServerToolResults }),
105
+ messages: await compressAnthropicMessages(compressor, params.messages, model, roleAggr, {
106
+ stripServerToolResults,
107
+ skipToolName: webSearch ? "ttc_web_search" : undefined,
108
+ }),
105
109
  };
106
110
  }
107
111
  if (systemAggr != null && typeof params?.system === "string" && params.system.trim()) {
@@ -116,7 +120,7 @@ export function withCompression(client, options) {
116
120
  let response = await originalCreate(params, ...rest);
117
121
  // Handle search tool loop
118
122
  if (webSearch) {
119
- response = await handleSearchLoop(response, params, originalCreate, ttcClient, rest);
123
+ response = await handleSearchLoop(response, params, originalCreate, ttcClient, stats, rest);
120
124
  }
121
125
  return response;
122
126
  };
@@ -30,6 +30,7 @@ export declare function compressOpenAIMessages(ttc: Compressor, messages: OpenAI
30
30
  interface AnthropicBlock {
31
31
  type: string;
32
32
  text?: string;
33
+ tool_use_id?: string;
33
34
  content?: string | Array<{
34
35
  type: string;
35
36
  text?: string;
@@ -44,6 +45,7 @@ interface AnthropicMessage {
44
45
  }
45
46
  export declare function compressAnthropicMessages(ttc: Compressor, messages: AnthropicMessage[], model: string, roleAggr: Record<string, number>, options?: {
46
47
  stripServerToolResults?: boolean;
48
+ skipToolName?: string;
47
49
  }): Promise<AnthropicMessage[]>;
48
50
  interface AISDKTextPart {
49
51
  type: "text";
package/dist/compress.js CHANGED
@@ -47,8 +47,22 @@ export async function compressOpenAIMessages(ttc, messages, model, roleAggr) {
47
47
  return msg;
48
48
  }));
49
49
  }
50
+ function collectToolUseIds(messages, toolName) {
51
+ const ids = new Set();
52
+ for (const msg of messages) {
53
+ if (msg.role !== "assistant" || !Array.isArray(msg.content))
54
+ continue;
55
+ for (const block of msg.content) {
56
+ if (block.type === "tool_use" && block.name === toolName && block.id) {
57
+ ids.add(block.id);
58
+ }
59
+ }
60
+ }
61
+ return ids;
62
+ }
50
63
  export async function compressAnthropicMessages(ttc, messages, model, roleAggr, options) {
51
64
  const stripServerToolResults = options?.stripServerToolResults ?? false;
65
+ const skipIds = options?.skipToolName ? collectToolUseIds(messages, options.skipToolName) : undefined;
52
66
  return Promise.all(messages.map(async (msg) => {
53
67
  if (msg.role === "assistant") {
54
68
  const assistantAggr = roleAggr["assistant"];
@@ -75,7 +89,7 @@ export async function compressAnthropicMessages(ttc, messages, model, roleAggr,
75
89
  return { ...msg, content: result.output };
76
90
  }
77
91
  if (Array.isArray(msg.content)) {
78
- const blocks = await compressAnthropicBlocks(ttc, msg.content, model, userAggr, toolAggr);
92
+ const blocks = await compressAnthropicBlocks(ttc, msg.content, model, userAggr, toolAggr, skipIds);
79
93
  return { ...msg, content: blocks };
80
94
  }
81
95
  return msg;
@@ -95,13 +109,15 @@ async function compressAssistantBlocks(ttc, blocks, model, assistantAggr, stripS
95
109
  const filtered = results.filter((b) => b != null);
96
110
  return filtered.length > 0 ? filtered : blocks;
97
111
  }
98
- async function compressAnthropicBlocks(ttc, blocks, model, userAggr, toolAggr) {
112
+ async function compressAnthropicBlocks(ttc, blocks, model, userAggr, toolAggr, skipIds) {
99
113
  return Promise.all(blocks.map(async (block) => {
100
114
  if (block.type === "text" && userAggr != null && typeof block.text === "string" && block.text.trim()) {
101
115
  const result = await ttc.compress(block.text, { model, aggressiveness: userAggr });
102
116
  return { ...block, text: result.output };
103
117
  }
104
118
  if (block.type === "tool_result" && toolAggr != null) {
119
+ if (block.tool_use_id && skipIds?.has(block.tool_use_id))
120
+ return block;
105
121
  return compressToolResult(ttc, block, model, toolAggr);
106
122
  }
107
123
  return block;
package/dist/types.d.ts CHANGED
@@ -76,6 +76,7 @@ export declare class CompressionStats {
76
76
  private _accumulator;
77
77
  _startTurn(): void;
78
78
  _record(result: CompressResult): void;
79
+ _recordSearch(result: SearchResult): void;
79
80
  _endTurn(): void;
80
81
  get totalInputTokens(): number;
81
82
  get totalOutputTokens(): number;
package/dist/types.js CHANGED
@@ -7,6 +7,16 @@ export class CompressionStats {
7
7
  _record(result) {
8
8
  this._accumulator.push(result);
9
9
  }
10
+ _recordSearch(result) {
11
+ this.history.push({
12
+ inputTokens: result.originalInputTokens,
13
+ outputTokens: result.outputTokens,
14
+ tokensSaved: result.tokensSaved,
15
+ messagesCompressed: 0,
16
+ ratio: result.outputTokens === 0 ? 0 : result.originalInputTokens / result.outputTokens,
17
+ timestamp: Date.now(),
18
+ });
19
+ }
10
20
  _endTurn() {
11
21
  if (this._accumulator.length > 0) {
12
22
  const inputTokens = this._accumulator.reduce((s, r) => s + r.inputTokens, 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "the-token-company",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Node.js SDK for The Token Company — compress LLM prompts to reduce costs and latency",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",