@ato-sdk/js 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,17 +1,17 @@
1
- # @agentic-tool-optimization/sdk
1
+ # @ato-sdk/js
2
2
 
3
3
  Auto-capture LLM traces for [ATO](https://agentictool.ai). Works with Anthropic, OpenAI, and any LLM provider.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install @agentic-tool-optimization/sdk
8
+ npm install @ato-sdk/js
9
9
  ```
10
10
 
11
11
  ## Quick Start
12
12
 
13
13
  ```typescript
14
- import { init } from '@agentic-tool-optimization/sdk';
14
+ import { init } from '@ato-sdk/js';
15
15
 
16
16
  // Initialize with your ATO API key
17
17
  init({ apiKey: 'your-ato-api-key' });
@@ -21,7 +21,7 @@ init({ apiKey: 'your-ato-api-key' });
21
21
 
22
22
  ```typescript
23
23
  import Anthropic from '@anthropic-ai/sdk';
24
- import { wrapAnthropic } from '@agentic-tool-optimization/sdk/anthropic';
24
+ import { wrapAnthropic } from '@ato-sdk/js/anthropic';
25
25
 
26
26
  const client = wrapAnthropic(new Anthropic());
27
27
 
@@ -37,7 +37,7 @@ const msg = await client.messages.create({
37
37
 
38
38
  ```typescript
39
39
  import OpenAI from 'openai';
40
- import { wrapOpenAI } from '@agentic-tool-optimization/sdk/openai';
40
+ import { wrapOpenAI } from '@ato-sdk/js/openai';
41
41
 
42
42
  const client = wrapOpenAI(new OpenAI());
43
43
 
@@ -81,8 +81,8 @@ init({
81
81
  For custom LLM providers:
82
82
 
83
83
  ```typescript
84
- import { capture, generateTraceId } from '@agentic-tool-optimization/sdk';
85
- import { calculateCost } from '@agentic-tool-optimization/sdk';
84
+ import { capture, generateTraceId } from '@ato-sdk/js';
85
+ import { calculateCost } from '@ato-sdk/js';
86
86
 
87
87
  capture({
88
88
  id: generateTraceId(),
@@ -105,7 +105,7 @@ capture({
105
105
  Built-in pricing for 60+ models:
106
106
 
107
107
  ```typescript
108
- import { calculateCost } from '@agentic-tool-optimization/sdk';
108
+ import { calculateCost } from '@ato-sdk/js';
109
109
 
110
110
  calculateCost('claude-sonnet-4-6', 1000, 500); // $0.0105
111
111
  calculateCost('gpt-4o', 1000, 500); // $0.0075
@@ -0,0 +1,23 @@
1
+ export { A as AtoConfig, a as AtoTrace, M as MODEL_PRICING, c as calculateCost, g as getClient, i as init } from './pricing-DnUk84wO.mjs';
2
+
3
+ /**
4
+ * ATO wrapper for the Claude Agent SDK
5
+ *
6
+ * Usage:
7
+ * import { Agent } from 'claude-agent-sdk';
8
+ * import { wrapAgent } from '@ato-sdk/js/agent';
9
+ *
10
+ * const agent = wrapAgent(new Agent({ model: 'claude-sonnet-4-6' }));
11
+ * // All agent runs are now auto-traced
12
+ * const result = await agent.run('Fix the failing tests');
13
+ */
14
+ type AgentInstance = {
15
+ run: (...args: any[]) => any;
16
+ [key: string]: any;
17
+ };
18
+ /**
19
+ * Wrap a Claude Agent SDK instance to auto-capture traces
20
+ */
21
+ declare function wrapAgent<T extends AgentInstance>(agent: T): T;
22
+
23
+ export { wrapAgent };
@@ -0,0 +1,23 @@
1
+ export { A as AtoConfig, a as AtoTrace, M as MODEL_PRICING, c as calculateCost, g as getClient, i as init } from './pricing-DnUk84wO.js';
2
+
3
+ /**
4
+ * ATO wrapper for the Claude Agent SDK
5
+ *
6
+ * Usage:
7
+ * import { Agent } from 'claude-agent-sdk';
8
+ * import { wrapAgent } from '@ato-sdk/js/agent';
9
+ *
10
+ * const agent = wrapAgent(new Agent({ model: 'claude-sonnet-4-6' }));
11
+ * // All agent runs are now auto-traced
12
+ * const result = await agent.run('Fix the failing tests');
13
+ */
14
+ type AgentInstance = {
15
+ run: (...args: any[]) => any;
16
+ [key: string]: any;
17
+ };
18
+ /**
19
+ * Wrap a Claude Agent SDK instance to auto-capture traces
20
+ */
21
+ declare function wrapAgent<T extends AgentInstance>(agent: T): T;
22
+
23
+ export { wrapAgent };
package/dist/agent.js ADDED
@@ -0,0 +1,319 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/agent.ts
21
+ var agent_exports = {};
22
+ __export(agent_exports, {
23
+ MODEL_PRICING: () => MODEL_PRICING,
24
+ calculateCost: () => calculateCost,
25
+ getClient: () => getClient,
26
+ init: () => init,
27
+ wrapAgent: () => wrapAgent
28
+ });
29
+ module.exports = __toCommonJS(agent_exports);
30
+
31
+ // src/client.ts
32
+ var SDK_VERSION = "0.1.0";
33
+ var DEFAULT_ENDPOINT = "https://api.agentictool.ai";
34
+ var DEFAULT_FLUSH_INTERVAL = 5e3;
35
+ var DEFAULT_MAX_BATCH_SIZE = 50;
36
+ var globalClient = null;
37
+ var AtoClient = class {
38
+ constructor(config = {}) {
39
+ this.queue = [];
40
+ this.timer = null;
41
+ this.config = {
42
+ endpoint: DEFAULT_ENDPOINT,
43
+ batching: true,
44
+ flushInterval: DEFAULT_FLUSH_INTERVAL,
45
+ maxBatchSize: DEFAULT_MAX_BATCH_SIZE,
46
+ debug: false,
47
+ localOnly: false,
48
+ ...config
49
+ };
50
+ if (this.config.batching && !this.config.localOnly) {
51
+ this.timer = setInterval(() => this.flush(), this.config.flushInterval);
52
+ if (this.timer && typeof this.timer === "object" && "unref" in this.timer) {
53
+ this.timer.unref();
54
+ }
55
+ }
56
+ }
57
+ /**
58
+ * Record a trace
59
+ */
60
+ capture(trace) {
61
+ if (this.config.defaultTags) {
62
+ trace.tags = [...trace.tags || [], ...this.config.defaultTags];
63
+ }
64
+ if (this.config.defaultMetadata) {
65
+ trace.metadata = { ...this.config.defaultMetadata, ...trace.metadata };
66
+ }
67
+ if (this.config.sessionId && !trace.sessionId) {
68
+ trace.sessionId = this.config.sessionId;
69
+ }
70
+ if (this.config.userId && !trace.userId) {
71
+ trace.userId = this.config.userId;
72
+ }
73
+ if (this.config.debug) {
74
+ console.log("[ato]", JSON.stringify(trace, null, 2));
75
+ }
76
+ if (this.config.localOnly) return;
77
+ this.queue.push(trace);
78
+ if (!this.config.batching || this.queue.length >= this.config.maxBatchSize) {
79
+ this.flush();
80
+ }
81
+ }
82
+ /**
83
+ * Flush pending traces to ATO Cloud
84
+ */
85
+ async flush() {
86
+ if (this.queue.length === 0) return;
87
+ const traces = this.queue.splice(0);
88
+ const payload = {
89
+ traces,
90
+ sdk: "@ato/sdk",
91
+ sdkVersion: SDK_VERSION,
92
+ sentAt: (/* @__PURE__ */ new Date()).toISOString()
93
+ };
94
+ try {
95
+ const headers = {
96
+ "Content-Type": "application/json"
97
+ };
98
+ if (this.config.apiKey) {
99
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
100
+ }
101
+ const res = await fetch(`${this.config.endpoint}/api/analytics/ingest`, {
102
+ method: "POST",
103
+ headers,
104
+ body: JSON.stringify(payload)
105
+ });
106
+ if (!res.ok && this.config.debug) {
107
+ console.error("[ato] Failed to send traces:", res.status, await res.text());
108
+ }
109
+ } catch (err) {
110
+ if (this.config.debug) {
111
+ console.error("[ato] Failed to send traces:", err);
112
+ }
113
+ this.queue.unshift(...traces);
114
+ if (this.queue.length > 1e3) {
115
+ this.queue.splice(0, this.queue.length - 500);
116
+ }
117
+ }
118
+ }
119
+ /**
120
+ * Shutdown — flush remaining traces
121
+ */
122
+ async shutdown() {
123
+ if (this.timer) {
124
+ clearInterval(this.timer);
125
+ this.timer = null;
126
+ }
127
+ await this.flush();
128
+ }
129
+ getConfig() {
130
+ return { ...this.config };
131
+ }
132
+ };
133
+ function init(config = {}) {
134
+ globalClient = new AtoClient(config);
135
+ return globalClient;
136
+ }
137
+ function getClient() {
138
+ if (!globalClient) {
139
+ globalClient = new AtoClient();
140
+ }
141
+ return globalClient;
142
+ }
143
+ function generateTraceId() {
144
+ return `ato_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
145
+ }
146
+
147
+ // src/pricing.ts
148
+ var MODEL_PRICING = {
149
+ // Anthropic
150
+ "claude-opus-4-6": { input: 15, output: 75, cached: 1.5 },
151
+ "claude-sonnet-4-6": { input: 3, output: 15, cached: 0.3 },
152
+ "claude-haiku-4-5": { input: 0.8, output: 4, cached: 0.08 },
153
+ "claude-sonnet-4-5": { input: 3, output: 15, cached: 0.3 },
154
+ "claude-3-5-sonnet": { input: 3, output: 15, cached: 0.3 },
155
+ "claude-3-5-haiku": { input: 0.8, output: 4, cached: 0.08 },
156
+ "claude-3-opus": { input: 15, output: 75, cached: 1.5 },
157
+ "claude-3-sonnet": { input: 3, output: 15 },
158
+ "claude-3-haiku": { input: 0.25, output: 1.25 },
159
+ // OpenAI
160
+ "gpt-4o": { input: 2.5, output: 10, cached: 1.25 },
161
+ "gpt-4o-mini": { input: 0.15, output: 0.6, cached: 0.075 },
162
+ "gpt-4-turbo": { input: 10, output: 30 },
163
+ "gpt-4": { input: 30, output: 60 },
164
+ "gpt-3.5-turbo": { input: 0.5, output: 1.5 },
165
+ "o1": { input: 15, output: 60, cached: 7.5 },
166
+ "o1-mini": { input: 3, output: 12, cached: 1.5 },
167
+ "o1-pro": { input: 150, output: 600 },
168
+ "o3": { input: 10, output: 40, cached: 2.5 },
169
+ "o3-mini": { input: 1.1, output: 4.4, cached: 0.55 },
170
+ "o4-mini": { input: 1.1, output: 4.4, cached: 0.275 },
171
+ "gpt-4.1": { input: 2, output: 8, cached: 0.5 },
172
+ "gpt-4.1-mini": { input: 0.4, output: 1.6, cached: 0.1 },
173
+ "gpt-4.1-nano": { input: 0.1, output: 0.4, cached: 0.025 },
174
+ // Google
175
+ "gemini-2.5-pro": { input: 1.25, output: 10 },
176
+ "gemini-2.5-flash": { input: 0.15, output: 0.6 },
177
+ "gemini-2.0-flash": { input: 0.1, output: 0.4 },
178
+ "gemini-1.5-pro": { input: 1.25, output: 5 },
179
+ "gemini-1.5-flash": { input: 0.075, output: 0.3 },
180
+ // Mistral
181
+ "mistral-large": { input: 2, output: 6 },
182
+ "mistral-small": { input: 0.2, output: 0.6 },
183
+ "codestral": { input: 0.3, output: 0.9 },
184
+ // Groq (inference pricing)
185
+ "llama-3.3-70b": { input: 0.59, output: 0.79 },
186
+ "llama-3.1-8b": { input: 0.05, output: 0.08 },
187
+ "mixtral-8x7b": { input: 0.24, output: 0.24 },
188
+ // Cohere
189
+ "command-r-plus": { input: 2.5, output: 10 },
190
+ "command-r": { input: 0.15, output: 0.6 }
191
+ };
192
+ function calculateCost(model, inputTokens, outputTokens, cachedTokens = 0) {
193
+ const pricing = MODEL_PRICING[model] || Object.entries(MODEL_PRICING).find(
194
+ ([key]) => model.startsWith(key)
195
+ )?.[1];
196
+ if (!pricing) return 0;
197
+ const inputCost = (inputTokens - cachedTokens) / 1e6 * pricing.input;
198
+ const outputCost = outputTokens / 1e6 * pricing.output;
199
+ const cachedCost = pricing.cached ? cachedTokens / 1e6 * pricing.cached : 0;
200
+ return inputCost + outputCost + cachedCost;
201
+ }
202
+
203
+ // src/agent.ts
204
+ function wrapAgent(agent) {
205
+ const originalRun = agent.run.bind(agent);
206
+ agent.run = async function(...args) {
207
+ const prompt = typeof args[0] === "string" ? args[0] : args[0]?.prompt || "";
208
+ const start = Date.now();
209
+ let totalInputTokens = 0;
210
+ let totalOutputTokens = 0;
211
+ let totalCachedTokens = 0;
212
+ let model = agent.model || "claude-sonnet-4-6";
213
+ let toolCalls = 0;
214
+ let status = "success";
215
+ let error;
216
+ try {
217
+ const result = originalRun(...args);
218
+ if (result && Symbol.asyncIterator in result) {
219
+ const originalIterator = result[Symbol.asyncIterator].bind(result);
220
+ result[Symbol.asyncIterator] = async function* () {
221
+ for await (const message of originalIterator()) {
222
+ if (message.type === "usage" || message.usage) {
223
+ const usage = message.usage || message;
224
+ totalInputTokens += usage.input_tokens || 0;
225
+ totalOutputTokens += usage.output_tokens || 0;
226
+ totalCachedTokens += usage.cache_read_input_tokens || 0;
227
+ }
228
+ if (message.type === "tool_use" || message.type === "tool_call") {
229
+ toolCalls++;
230
+ }
231
+ if (message.model) {
232
+ model = message.model;
233
+ }
234
+ yield message;
235
+ }
236
+ captureAgentTrace({
237
+ start,
238
+ model,
239
+ prompt,
240
+ totalInputTokens,
241
+ totalOutputTokens,
242
+ totalCachedTokens,
243
+ toolCalls,
244
+ status,
245
+ error
246
+ });
247
+ };
248
+ return result;
249
+ }
250
+ const awaited = await result;
251
+ if (awaited?.usage) {
252
+ totalInputTokens = awaited.usage.input_tokens || 0;
253
+ totalOutputTokens = awaited.usage.output_tokens || 0;
254
+ totalCachedTokens = awaited.usage.cache_read_input_tokens || 0;
255
+ }
256
+ if (awaited?.model) model = awaited.model;
257
+ if (awaited?.tool_calls) toolCalls = awaited.tool_calls;
258
+ captureAgentTrace({
259
+ start,
260
+ model,
261
+ prompt,
262
+ totalInputTokens,
263
+ totalOutputTokens,
264
+ totalCachedTokens,
265
+ toolCalls,
266
+ status,
267
+ error
268
+ });
269
+ return awaited;
270
+ } catch (err) {
271
+ status = "error";
272
+ error = err.message || String(err);
273
+ captureAgentTrace({
274
+ start,
275
+ model,
276
+ prompt,
277
+ totalInputTokens,
278
+ totalOutputTokens,
279
+ totalCachedTokens,
280
+ toolCalls,
281
+ status,
282
+ error
283
+ });
284
+ throw err;
285
+ }
286
+ };
287
+ return agent;
288
+ }
289
+ function captureAgentTrace(params) {
290
+ const duration = Date.now() - params.start;
291
+ const trace = {
292
+ id: generateTraceId(),
293
+ provider: "anthropic-agent",
294
+ model: params.model,
295
+ inputTokens: params.totalInputTokens,
296
+ outputTokens: params.totalOutputTokens,
297
+ cachedTokens: params.totalCachedTokens,
298
+ totalTokens: params.totalInputTokens + params.totalOutputTokens,
299
+ costUsd: calculateCost(params.model, params.totalInputTokens, params.totalOutputTokens, params.totalCachedTokens),
300
+ durationMs: duration,
301
+ status: params.status,
302
+ error: params.error,
303
+ metadata: {
304
+ type: "agent-session",
305
+ prompt: params.prompt.slice(0, 200),
306
+ toolCalls: params.toolCalls
307
+ },
308
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
309
+ };
310
+ getClient().capture(trace);
311
+ }
312
+ // Annotate the CommonJS export names for ESM import in node:
313
+ 0 && (module.exports = {
314
+ MODEL_PRICING,
315
+ calculateCost,
316
+ getClient,
317
+ init,
318
+ wrapAgent
319
+ });
package/dist/agent.mjs ADDED
@@ -0,0 +1,124 @@
1
+ import {
2
+ MODEL_PRICING,
3
+ calculateCost,
4
+ generateTraceId,
5
+ getClient,
6
+ init
7
+ } from "./chunk-Q2LJUUHK.mjs";
8
+
9
+ // src/agent.ts
10
+ function wrapAgent(agent) {
11
+ const originalRun = agent.run.bind(agent);
12
+ agent.run = async function(...args) {
13
+ const prompt = typeof args[0] === "string" ? args[0] : args[0]?.prompt || "";
14
+ const start = Date.now();
15
+ let totalInputTokens = 0;
16
+ let totalOutputTokens = 0;
17
+ let totalCachedTokens = 0;
18
+ let model = agent.model || "claude-sonnet-4-6";
19
+ let toolCalls = 0;
20
+ let status = "success";
21
+ let error;
22
+ try {
23
+ const result = originalRun(...args);
24
+ if (result && Symbol.asyncIterator in result) {
25
+ const originalIterator = result[Symbol.asyncIterator].bind(result);
26
+ result[Symbol.asyncIterator] = async function* () {
27
+ for await (const message of originalIterator()) {
28
+ if (message.type === "usage" || message.usage) {
29
+ const usage = message.usage || message;
30
+ totalInputTokens += usage.input_tokens || 0;
31
+ totalOutputTokens += usage.output_tokens || 0;
32
+ totalCachedTokens += usage.cache_read_input_tokens || 0;
33
+ }
34
+ if (message.type === "tool_use" || message.type === "tool_call") {
35
+ toolCalls++;
36
+ }
37
+ if (message.model) {
38
+ model = message.model;
39
+ }
40
+ yield message;
41
+ }
42
+ captureAgentTrace({
43
+ start,
44
+ model,
45
+ prompt,
46
+ totalInputTokens,
47
+ totalOutputTokens,
48
+ totalCachedTokens,
49
+ toolCalls,
50
+ status,
51
+ error
52
+ });
53
+ };
54
+ return result;
55
+ }
56
+ const awaited = await result;
57
+ if (awaited?.usage) {
58
+ totalInputTokens = awaited.usage.input_tokens || 0;
59
+ totalOutputTokens = awaited.usage.output_tokens || 0;
60
+ totalCachedTokens = awaited.usage.cache_read_input_tokens || 0;
61
+ }
62
+ if (awaited?.model) model = awaited.model;
63
+ if (awaited?.tool_calls) toolCalls = awaited.tool_calls;
64
+ captureAgentTrace({
65
+ start,
66
+ model,
67
+ prompt,
68
+ totalInputTokens,
69
+ totalOutputTokens,
70
+ totalCachedTokens,
71
+ toolCalls,
72
+ status,
73
+ error
74
+ });
75
+ return awaited;
76
+ } catch (err) {
77
+ status = "error";
78
+ error = err.message || String(err);
79
+ captureAgentTrace({
80
+ start,
81
+ model,
82
+ prompt,
83
+ totalInputTokens,
84
+ totalOutputTokens,
85
+ totalCachedTokens,
86
+ toolCalls,
87
+ status,
88
+ error
89
+ });
90
+ throw err;
91
+ }
92
+ };
93
+ return agent;
94
+ }
95
+ function captureAgentTrace(params) {
96
+ const duration = Date.now() - params.start;
97
+ const trace = {
98
+ id: generateTraceId(),
99
+ provider: "anthropic-agent",
100
+ model: params.model,
101
+ inputTokens: params.totalInputTokens,
102
+ outputTokens: params.totalOutputTokens,
103
+ cachedTokens: params.totalCachedTokens,
104
+ totalTokens: params.totalInputTokens + params.totalOutputTokens,
105
+ costUsd: calculateCost(params.model, params.totalInputTokens, params.totalOutputTokens, params.totalCachedTokens),
106
+ durationMs: duration,
107
+ status: params.status,
108
+ error: params.error,
109
+ metadata: {
110
+ type: "agent-session",
111
+ prompt: params.prompt.slice(0, 200),
112
+ toolCalls: params.toolCalls
113
+ },
114
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
115
+ };
116
+ getClient().capture(trace);
117
+ }
118
+ export {
119
+ MODEL_PRICING,
120
+ calculateCost,
121
+ getClient,
122
+ init,
123
+ wrapAgent
124
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ato-sdk/js",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Auto-capture LLM traces for ATO — works with Anthropic, OpenAI, and any LLM provider",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -20,14 +20,19 @@
20
20
  "import": "./dist/openai.mjs",
21
21
  "require": "./dist/openai.js",
22
22
  "types": "./dist/openai.d.ts"
23
+ },
24
+ "./agent": {
25
+ "import": "./dist/agent.mjs",
26
+ "require": "./dist/agent.js",
27
+ "types": "./dist/agent.d.ts"
23
28
  }
24
29
  },
25
30
  "files": [
26
31
  "dist"
27
32
  ],
28
33
  "scripts": {
29
- "build": "tsup src/index.ts src/anthropic.ts src/openai.ts --format cjs,esm --dts --clean",
30
- "dev": "tsup src/index.ts src/anthropic.ts src/openai.ts --format cjs,esm --dts --watch"
34
+ "build": "tsup src/index.ts src/anthropic.ts src/openai.ts src/agent.ts --format cjs,esm --dts --clean",
35
+ "dev": "tsup src/index.ts src/anthropic.ts src/openai.ts src/agent.ts --format cjs,esm --dts --watch"
31
36
  },
32
37
  "keywords": [
33
38
  "ato",
@@ -58,6 +63,7 @@
58
63
  },
59
64
  "peerDependenciesMeta": {
60
65
  "@anthropic-ai/sdk": { "optional": true },
61
- "openai": { "optional": true }
66
+ "openai": { "optional": true },
67
+ "claude-agent-sdk": { "optional": true }
62
68
  }
63
69
  }