@snap-agent/analytics-console 0.1.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/LICENSE +22 -0
- package/README.md +195 -0
- package/dist/index.d.mts +111 -0
- package/dist/index.d.ts +111 -0
- package/dist/index.js +214 -0
- package/dist/index.mjs +187 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 ViloTech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# @snap-agent/analytics-console
|
|
2
|
+
|
|
3
|
+
Console analytics plugin for SnapAgent SDK - Pretty-print metrics to terminal for debugging.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Pretty Console Output** - Color-coded, formatted logs
|
|
8
|
+
- **Three Log Levels** - Minimal, standard, verbose
|
|
9
|
+
- **Periodic Summaries** - Automatic stats output
|
|
10
|
+
- **Colorful** - Easy to scan terminal output
|
|
11
|
+
- **Perfect for Dev** - Quick debugging during development
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @snap-agent/analytics-console @snap-agent/core
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { createClient, MemoryStorage } from '@snap-agent/core';
|
|
23
|
+
import { ConsoleAnalytics } from '@snap-agent/analytics-console';
|
|
24
|
+
|
|
25
|
+
const client = createClient({
|
|
26
|
+
storage: new MemoryStorage(),
|
|
27
|
+
providers: {
|
|
28
|
+
openai: { apiKey: process.env.OPENAI_API_KEY! },
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const agent = await client.createAgent({
|
|
33
|
+
name: 'Debug Demo',
|
|
34
|
+
instructions: 'You are helpful.',
|
|
35
|
+
model: 'gpt-4o',
|
|
36
|
+
userId: 'user-123',
|
|
37
|
+
plugins: [
|
|
38
|
+
new ConsoleAnalytics({
|
|
39
|
+
level: 'verbose',
|
|
40
|
+
}),
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Use the agent - see pretty logs!
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Output Examples
|
|
48
|
+
|
|
49
|
+
### Standard Level
|
|
50
|
+
```
|
|
51
|
+
[14:32:15.123] [SnapAgent] -> Request agent:abc12345 thread:xyz98765
|
|
52
|
+
[14:32:16.456] [SnapAgent] <- Response 1333ms 450 tokens agent:abc12345
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Verbose Level
|
|
56
|
+
```
|
|
57
|
+
[14:32:15.123] [SnapAgent] -> Request agent:abc12345 thread:xyz98765
|
|
58
|
+
Message: Hello, can you help me with...
|
|
59
|
+
|
|
60
|
+
[14:32:16.456] [SnapAgent] <- Response 1333ms 450 tokens agent:abc12345
|
|
61
|
+
Response: Of course! I'd be happy to help you with...
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Error
|
|
65
|
+
```
|
|
66
|
+
[14:32:17.789] [SnapAgent] x Error rate_limit agent:abc12345
|
|
67
|
+
Message: Rate limit exceeded. Please retry after 60 seconds.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Summary
|
|
71
|
+
```
|
|
72
|
+
[SnapAgent] Summary
|
|
73
|
+
----------------------------------------
|
|
74
|
+
Requests: 25
|
|
75
|
+
Responses: 24
|
|
76
|
+
Errors: 1
|
|
77
|
+
Avg Latency: 892ms
|
|
78
|
+
Avg Tokens: 380
|
|
79
|
+
Total Tokens: 9120
|
|
80
|
+
----------------------------------------
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
new ConsoleAnalytics({
|
|
87
|
+
// Log level: 'minimal' | 'standard' | 'verbose'
|
|
88
|
+
level: 'standard',
|
|
89
|
+
|
|
90
|
+
// Enable colored output
|
|
91
|
+
colors: true,
|
|
92
|
+
|
|
93
|
+
// Show timestamps
|
|
94
|
+
timestamps: true,
|
|
95
|
+
|
|
96
|
+
// Custom prefix
|
|
97
|
+
prefix: '[SnapAgent]',
|
|
98
|
+
|
|
99
|
+
// What to log
|
|
100
|
+
logRequests: true,
|
|
101
|
+
logResponses: true,
|
|
102
|
+
logErrors: true,
|
|
103
|
+
|
|
104
|
+
// Print summary every N ms (0 = disabled)
|
|
105
|
+
summaryInterval: 60000, // Every minute
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Log Levels
|
|
110
|
+
|
|
111
|
+
### `minimal`
|
|
112
|
+
Just counts, no details:
|
|
113
|
+
```
|
|
114
|
+
[SnapAgent] -> Request
|
|
115
|
+
[SnapAgent] <- Response 450ms
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `standard` (default)
|
|
119
|
+
Includes agent/thread IDs and tokens:
|
|
120
|
+
```
|
|
121
|
+
[SnapAgent] -> Request agent:abc12345 thread:xyz98765
|
|
122
|
+
[SnapAgent] <- Response 450ms 380 tokens agent:abc12345
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `verbose`
|
|
126
|
+
Full message content:
|
|
127
|
+
```
|
|
128
|
+
[SnapAgent] -> Request agent:abc12345 thread:xyz98765
|
|
129
|
+
Message: What is the weather like today?
|
|
130
|
+
|
|
131
|
+
[SnapAgent] <- Response 450ms 380 tokens agent:abc12345
|
|
132
|
+
Response: I don't have access to real-time weather data...
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## API
|
|
136
|
+
|
|
137
|
+
### `printSummary()`
|
|
138
|
+
Manually print the current summary:
|
|
139
|
+
```typescript
|
|
140
|
+
const analytics = new ConsoleAnalytics();
|
|
141
|
+
// ... use agent ...
|
|
142
|
+
analytics.printSummary();
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `reset()`
|
|
146
|
+
Reset all counters:
|
|
147
|
+
```typescript
|
|
148
|
+
analytics.reset();
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `getStats()`
|
|
152
|
+
Get current stats as object:
|
|
153
|
+
```typescript
|
|
154
|
+
const stats = analytics.getStats();
|
|
155
|
+
// { requests: 25, responses: 24, errors: 1, avgLatency: 892, totalTokens: 9120 }
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `destroy()`
|
|
159
|
+
Clean up (stops summary timer):
|
|
160
|
+
```typescript
|
|
161
|
+
analytics.destroy();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Color Reference
|
|
165
|
+
|
|
166
|
+
| Color | Meaning |
|
|
167
|
+
|-------|---------|
|
|
168
|
+
| Cyan | Requests |
|
|
169
|
+
| Green | Successful responses, fast latency (<500ms) |
|
|
170
|
+
| Yellow | Medium latency (500-2000ms) |
|
|
171
|
+
| Red | Errors, slow latency (>2000ms) |
|
|
172
|
+
| Dim | Metadata, IDs |
|
|
173
|
+
|
|
174
|
+
## Disable Colors
|
|
175
|
+
|
|
176
|
+
For CI/CD or piping to files:
|
|
177
|
+
```typescript
|
|
178
|
+
new ConsoleAnalytics({
|
|
179
|
+
colors: false,
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Use Cases
|
|
184
|
+
|
|
185
|
+
- **Local Development** - Quick visibility into agent behavior
|
|
186
|
+
- **Debugging** - See what's happening in real-time
|
|
187
|
+
- **Demos** - Show activity during presentations
|
|
188
|
+
- **Learning** - Understand the request/response flow
|
|
189
|
+
|
|
190
|
+
For production monitoring, use [@snap-agent/analytics](../core) instead.
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT © ViloTech
|
|
195
|
+
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { AnalyticsPlugin } from '@snap-agent/core';
|
|
2
|
+
|
|
3
|
+
type LogLevel = 'minimal' | 'standard' | 'verbose';
|
|
4
|
+
interface ConsoleAnalyticsConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Log level
|
|
7
|
+
* - minimal: Just request/response counts
|
|
8
|
+
* - standard: Include latency and tokens
|
|
9
|
+
* - verbose: Include all details
|
|
10
|
+
* @default 'standard'
|
|
11
|
+
*/
|
|
12
|
+
level?: LogLevel;
|
|
13
|
+
/**
|
|
14
|
+
* Enable colored output
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
colors?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Show timestamps
|
|
20
|
+
* @default true
|
|
21
|
+
*/
|
|
22
|
+
timestamps?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Prefix for log messages
|
|
25
|
+
* @default '[SnapAgent]'
|
|
26
|
+
*/
|
|
27
|
+
prefix?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Log requests
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
logRequests?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Log responses
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
logResponses?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Log errors
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
logErrors?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Show periodic summaries (interval in ms, 0 = disabled)
|
|
45
|
+
* @default 0
|
|
46
|
+
*/
|
|
47
|
+
summaryInterval?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Console Analytics Plugin
|
|
51
|
+
*
|
|
52
|
+
* Simple plugin that pretty-prints analytics to the console.
|
|
53
|
+
* Perfect for development and debugging.
|
|
54
|
+
*/
|
|
55
|
+
declare class ConsoleAnalytics implements AnalyticsPlugin {
|
|
56
|
+
name: string;
|
|
57
|
+
type: "analytics";
|
|
58
|
+
private config;
|
|
59
|
+
private requestCount;
|
|
60
|
+
private responseCount;
|
|
61
|
+
private errorCount;
|
|
62
|
+
private totalLatency;
|
|
63
|
+
private totalTokens;
|
|
64
|
+
private summaryTimer?;
|
|
65
|
+
constructor(config?: ConsoleAnalyticsConfig);
|
|
66
|
+
trackRequest(data: {
|
|
67
|
+
agentId: string;
|
|
68
|
+
threadId?: string;
|
|
69
|
+
message: string;
|
|
70
|
+
timestamp: Date;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
trackResponse(data: {
|
|
73
|
+
agentId: string;
|
|
74
|
+
threadId?: string;
|
|
75
|
+
response: string;
|
|
76
|
+
latency: number;
|
|
77
|
+
tokensUsed?: number;
|
|
78
|
+
timestamp: Date;
|
|
79
|
+
}): Promise<void>;
|
|
80
|
+
trackError(data: {
|
|
81
|
+
agentId: string;
|
|
82
|
+
threadId?: string;
|
|
83
|
+
timestamp: Date;
|
|
84
|
+
errorType: string;
|
|
85
|
+
errorMessage: string;
|
|
86
|
+
}): Promise<void>;
|
|
87
|
+
printSummary(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Reset counters
|
|
90
|
+
*/
|
|
91
|
+
reset(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Get current stats
|
|
94
|
+
*/
|
|
95
|
+
getStats(): Record<string, number>;
|
|
96
|
+
/**
|
|
97
|
+
* Stop summary timer
|
|
98
|
+
*/
|
|
99
|
+
destroy(): void;
|
|
100
|
+
private formatTime;
|
|
101
|
+
private truncate;
|
|
102
|
+
private formatLatency;
|
|
103
|
+
private bold;
|
|
104
|
+
private dim;
|
|
105
|
+
private green;
|
|
106
|
+
private yellow;
|
|
107
|
+
private red;
|
|
108
|
+
private cyan;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { ConsoleAnalytics, type ConsoleAnalyticsConfig, type LogLevel };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { AnalyticsPlugin } from '@snap-agent/core';
|
|
2
|
+
|
|
3
|
+
type LogLevel = 'minimal' | 'standard' | 'verbose';
|
|
4
|
+
interface ConsoleAnalyticsConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Log level
|
|
7
|
+
* - minimal: Just request/response counts
|
|
8
|
+
* - standard: Include latency and tokens
|
|
9
|
+
* - verbose: Include all details
|
|
10
|
+
* @default 'standard'
|
|
11
|
+
*/
|
|
12
|
+
level?: LogLevel;
|
|
13
|
+
/**
|
|
14
|
+
* Enable colored output
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
colors?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Show timestamps
|
|
20
|
+
* @default true
|
|
21
|
+
*/
|
|
22
|
+
timestamps?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Prefix for log messages
|
|
25
|
+
* @default '[SnapAgent]'
|
|
26
|
+
*/
|
|
27
|
+
prefix?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Log requests
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
logRequests?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Log responses
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
logResponses?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Log errors
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
logErrors?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Show periodic summaries (interval in ms, 0 = disabled)
|
|
45
|
+
* @default 0
|
|
46
|
+
*/
|
|
47
|
+
summaryInterval?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Console Analytics Plugin
|
|
51
|
+
*
|
|
52
|
+
* Simple plugin that pretty-prints analytics to the console.
|
|
53
|
+
* Perfect for development and debugging.
|
|
54
|
+
*/
|
|
55
|
+
declare class ConsoleAnalytics implements AnalyticsPlugin {
|
|
56
|
+
name: string;
|
|
57
|
+
type: "analytics";
|
|
58
|
+
private config;
|
|
59
|
+
private requestCount;
|
|
60
|
+
private responseCount;
|
|
61
|
+
private errorCount;
|
|
62
|
+
private totalLatency;
|
|
63
|
+
private totalTokens;
|
|
64
|
+
private summaryTimer?;
|
|
65
|
+
constructor(config?: ConsoleAnalyticsConfig);
|
|
66
|
+
trackRequest(data: {
|
|
67
|
+
agentId: string;
|
|
68
|
+
threadId?: string;
|
|
69
|
+
message: string;
|
|
70
|
+
timestamp: Date;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
trackResponse(data: {
|
|
73
|
+
agentId: string;
|
|
74
|
+
threadId?: string;
|
|
75
|
+
response: string;
|
|
76
|
+
latency: number;
|
|
77
|
+
tokensUsed?: number;
|
|
78
|
+
timestamp: Date;
|
|
79
|
+
}): Promise<void>;
|
|
80
|
+
trackError(data: {
|
|
81
|
+
agentId: string;
|
|
82
|
+
threadId?: string;
|
|
83
|
+
timestamp: Date;
|
|
84
|
+
errorType: string;
|
|
85
|
+
errorMessage: string;
|
|
86
|
+
}): Promise<void>;
|
|
87
|
+
printSummary(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Reset counters
|
|
90
|
+
*/
|
|
91
|
+
reset(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Get current stats
|
|
94
|
+
*/
|
|
95
|
+
getStats(): Record<string, number>;
|
|
96
|
+
/**
|
|
97
|
+
* Stop summary timer
|
|
98
|
+
*/
|
|
99
|
+
destroy(): void;
|
|
100
|
+
private formatTime;
|
|
101
|
+
private truncate;
|
|
102
|
+
private formatLatency;
|
|
103
|
+
private bold;
|
|
104
|
+
private dim;
|
|
105
|
+
private green;
|
|
106
|
+
private yellow;
|
|
107
|
+
private red;
|
|
108
|
+
private cyan;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { ConsoleAnalytics, type ConsoleAnalyticsConfig, type LogLevel };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
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/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ConsoleAnalytics: () => ConsoleAnalytics
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/ConsoleAnalytics.ts
|
|
28
|
+
var ConsoleAnalytics = class {
|
|
29
|
+
constructor(config = {}) {
|
|
30
|
+
this.name = "console-analytics";
|
|
31
|
+
this.type = "analytics";
|
|
32
|
+
this.requestCount = 0;
|
|
33
|
+
this.responseCount = 0;
|
|
34
|
+
this.errorCount = 0;
|
|
35
|
+
this.totalLatency = 0;
|
|
36
|
+
this.totalTokens = 0;
|
|
37
|
+
this.config = {
|
|
38
|
+
level: config.level || "standard",
|
|
39
|
+
colors: config.colors !== false,
|
|
40
|
+
timestamps: config.timestamps !== false,
|
|
41
|
+
prefix: config.prefix || "[SnapAgent]",
|
|
42
|
+
logRequests: config.logRequests !== false,
|
|
43
|
+
logResponses: config.logResponses !== false,
|
|
44
|
+
logErrors: config.logErrors !== false,
|
|
45
|
+
summaryInterval: config.summaryInterval || 0
|
|
46
|
+
};
|
|
47
|
+
if (this.config.summaryInterval > 0) {
|
|
48
|
+
this.summaryTimer = setInterval(
|
|
49
|
+
() => this.printSummary(),
|
|
50
|
+
this.config.summaryInterval
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Plugin Interface
|
|
56
|
+
// ============================================================================
|
|
57
|
+
async trackRequest(data) {
|
|
58
|
+
this.requestCount++;
|
|
59
|
+
if (!this.config.logRequests) return;
|
|
60
|
+
const parts = [];
|
|
61
|
+
if (this.config.timestamps) {
|
|
62
|
+
parts.push(this.dim(`[${this.formatTime(data.timestamp)}]`));
|
|
63
|
+
}
|
|
64
|
+
parts.push(this.config.prefix);
|
|
65
|
+
parts.push(this.cyan("\u2192 Request"));
|
|
66
|
+
if (this.config.level !== "minimal") {
|
|
67
|
+
parts.push(this.dim(`agent:${data.agentId.slice(0, 8)}`));
|
|
68
|
+
if (data.threadId) {
|
|
69
|
+
parts.push(this.dim(`thread:${data.threadId.slice(0, 8)}`));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (this.config.level === "verbose") {
|
|
73
|
+
parts.push(`
|
|
74
|
+
${this.dim("Message:")} ${this.truncate(data.message, 100)}`);
|
|
75
|
+
}
|
|
76
|
+
console.log(parts.join(" "));
|
|
77
|
+
}
|
|
78
|
+
async trackResponse(data) {
|
|
79
|
+
this.responseCount++;
|
|
80
|
+
this.totalLatency += data.latency;
|
|
81
|
+
this.totalTokens += data.tokensUsed || 0;
|
|
82
|
+
if (!this.config.logResponses) return;
|
|
83
|
+
const parts = [];
|
|
84
|
+
if (this.config.timestamps) {
|
|
85
|
+
parts.push(this.dim(`[${this.formatTime(data.timestamp)}]`));
|
|
86
|
+
}
|
|
87
|
+
parts.push(this.config.prefix);
|
|
88
|
+
parts.push(this.green("\u2190 Response"));
|
|
89
|
+
const latencyColor = data.latency < 500 ? "green" : data.latency < 2e3 ? "yellow" : "red";
|
|
90
|
+
parts.push(this[latencyColor](`${data.latency}ms`));
|
|
91
|
+
if (this.config.level !== "minimal" && data.tokensUsed) {
|
|
92
|
+
parts.push(this.dim(`${data.tokensUsed} tokens`));
|
|
93
|
+
}
|
|
94
|
+
if (this.config.level !== "minimal") {
|
|
95
|
+
parts.push(this.dim(`agent:${data.agentId.slice(0, 8)}`));
|
|
96
|
+
}
|
|
97
|
+
if (this.config.level === "verbose") {
|
|
98
|
+
parts.push(`
|
|
99
|
+
${this.dim("Response:")} ${this.truncate(data.response, 150)}`);
|
|
100
|
+
}
|
|
101
|
+
console.log(parts.join(" "));
|
|
102
|
+
}
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// Extended Tracking (Optional)
|
|
105
|
+
// ============================================================================
|
|
106
|
+
async trackError(data) {
|
|
107
|
+
this.errorCount++;
|
|
108
|
+
if (!this.config.logErrors) return;
|
|
109
|
+
const parts = [];
|
|
110
|
+
if (this.config.timestamps) {
|
|
111
|
+
parts.push(this.dim(`[${this.formatTime(data.timestamp)}]`));
|
|
112
|
+
}
|
|
113
|
+
parts.push(this.config.prefix);
|
|
114
|
+
parts.push(this.red("x Error"));
|
|
115
|
+
parts.push(this.red(data.errorType));
|
|
116
|
+
if (this.config.level !== "minimal") {
|
|
117
|
+
parts.push(this.dim(`agent:${data.agentId.slice(0, 8)}`));
|
|
118
|
+
}
|
|
119
|
+
if (this.config.level === "verbose") {
|
|
120
|
+
parts.push(`
|
|
121
|
+
${this.dim("Message:")} ${data.errorMessage}`);
|
|
122
|
+
}
|
|
123
|
+
console.log(parts.join(" "));
|
|
124
|
+
}
|
|
125
|
+
// ============================================================================
|
|
126
|
+
// Summary
|
|
127
|
+
// ============================================================================
|
|
128
|
+
printSummary() {
|
|
129
|
+
const avgLatency = this.responseCount > 0 ? Math.round(this.totalLatency / this.responseCount) : 0;
|
|
130
|
+
const avgTokens = this.responseCount > 0 ? Math.round(this.totalTokens / this.responseCount) : 0;
|
|
131
|
+
console.log("");
|
|
132
|
+
console.log(this.bold(`${this.config.prefix} Summary`));
|
|
133
|
+
console.log(this.dim("\u2500".repeat(40)));
|
|
134
|
+
console.log(` Requests: ${this.cyan(this.requestCount.toString())}`);
|
|
135
|
+
console.log(` Responses: ${this.green(this.responseCount.toString())}`);
|
|
136
|
+
console.log(` Errors: ${this.errorCount > 0 ? this.red(this.errorCount.toString()) : this.dim("0")}`);
|
|
137
|
+
console.log(` Avg Latency: ${this.formatLatency(avgLatency)}`);
|
|
138
|
+
console.log(` Avg Tokens: ${this.dim(avgTokens.toString())}`);
|
|
139
|
+
console.log(` Total Tokens: ${this.dim(this.totalTokens.toString())}`);
|
|
140
|
+
console.log(this.dim("\u2500".repeat(40)));
|
|
141
|
+
console.log("");
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Reset counters
|
|
145
|
+
*/
|
|
146
|
+
reset() {
|
|
147
|
+
this.requestCount = 0;
|
|
148
|
+
this.responseCount = 0;
|
|
149
|
+
this.errorCount = 0;
|
|
150
|
+
this.totalLatency = 0;
|
|
151
|
+
this.totalTokens = 0;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get current stats
|
|
155
|
+
*/
|
|
156
|
+
getStats() {
|
|
157
|
+
return {
|
|
158
|
+
requests: this.requestCount,
|
|
159
|
+
responses: this.responseCount,
|
|
160
|
+
errors: this.errorCount,
|
|
161
|
+
avgLatency: this.responseCount > 0 ? Math.round(this.totalLatency / this.responseCount) : 0,
|
|
162
|
+
totalTokens: this.totalTokens
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Stop summary timer
|
|
167
|
+
*/
|
|
168
|
+
destroy() {
|
|
169
|
+
if (this.summaryTimer) {
|
|
170
|
+
clearInterval(this.summaryTimer);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// ============================================================================
|
|
174
|
+
// Formatting Helpers
|
|
175
|
+
// ============================================================================
|
|
176
|
+
formatTime(date) {
|
|
177
|
+
return date.toISOString().slice(11, 23);
|
|
178
|
+
}
|
|
179
|
+
truncate(str, maxLen) {
|
|
180
|
+
const cleaned = str.replace(/\n/g, " ").trim();
|
|
181
|
+
if (cleaned.length <= maxLen) return cleaned;
|
|
182
|
+
return cleaned.slice(0, maxLen - 3) + "...";
|
|
183
|
+
}
|
|
184
|
+
formatLatency(ms) {
|
|
185
|
+
if (ms < 500) return this.green(`${ms}ms`);
|
|
186
|
+
if (ms < 2e3) return this.yellow(`${ms}ms`);
|
|
187
|
+
return this.red(`${ms}ms`);
|
|
188
|
+
}
|
|
189
|
+
// ============================================================================
|
|
190
|
+
// Color Helpers
|
|
191
|
+
// ============================================================================
|
|
192
|
+
bold(text) {
|
|
193
|
+
return this.config.colors ? `\x1B[1m${text}\x1B[0m` : text;
|
|
194
|
+
}
|
|
195
|
+
dim(text) {
|
|
196
|
+
return this.config.colors ? `\x1B[2m${text}\x1B[0m` : text;
|
|
197
|
+
}
|
|
198
|
+
green(text) {
|
|
199
|
+
return this.config.colors ? `\x1B[32m${text}\x1B[0m` : text;
|
|
200
|
+
}
|
|
201
|
+
yellow(text) {
|
|
202
|
+
return this.config.colors ? `\x1B[33m${text}\x1B[0m` : text;
|
|
203
|
+
}
|
|
204
|
+
red(text) {
|
|
205
|
+
return this.config.colors ? `\x1B[31m${text}\x1B[0m` : text;
|
|
206
|
+
}
|
|
207
|
+
cyan(text) {
|
|
208
|
+
return this.config.colors ? `\x1B[36m${text}\x1B[0m` : text;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
212
|
+
0 && (module.exports = {
|
|
213
|
+
ConsoleAnalytics
|
|
214
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// src/ConsoleAnalytics.ts
|
|
2
|
+
var ConsoleAnalytics = class {
|
|
3
|
+
constructor(config = {}) {
|
|
4
|
+
this.name = "console-analytics";
|
|
5
|
+
this.type = "analytics";
|
|
6
|
+
this.requestCount = 0;
|
|
7
|
+
this.responseCount = 0;
|
|
8
|
+
this.errorCount = 0;
|
|
9
|
+
this.totalLatency = 0;
|
|
10
|
+
this.totalTokens = 0;
|
|
11
|
+
this.config = {
|
|
12
|
+
level: config.level || "standard",
|
|
13
|
+
colors: config.colors !== false,
|
|
14
|
+
timestamps: config.timestamps !== false,
|
|
15
|
+
prefix: config.prefix || "[SnapAgent]",
|
|
16
|
+
logRequests: config.logRequests !== false,
|
|
17
|
+
logResponses: config.logResponses !== false,
|
|
18
|
+
logErrors: config.logErrors !== false,
|
|
19
|
+
summaryInterval: config.summaryInterval || 0
|
|
20
|
+
};
|
|
21
|
+
if (this.config.summaryInterval > 0) {
|
|
22
|
+
this.summaryTimer = setInterval(
|
|
23
|
+
() => this.printSummary(),
|
|
24
|
+
this.config.summaryInterval
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Plugin Interface
|
|
30
|
+
// ============================================================================
|
|
31
|
+
async trackRequest(data) {
|
|
32
|
+
this.requestCount++;
|
|
33
|
+
if (!this.config.logRequests) return;
|
|
34
|
+
const parts = [];
|
|
35
|
+
if (this.config.timestamps) {
|
|
36
|
+
parts.push(this.dim(`[${this.formatTime(data.timestamp)}]`));
|
|
37
|
+
}
|
|
38
|
+
parts.push(this.config.prefix);
|
|
39
|
+
parts.push(this.cyan("\u2192 Request"));
|
|
40
|
+
if (this.config.level !== "minimal") {
|
|
41
|
+
parts.push(this.dim(`agent:${data.agentId.slice(0, 8)}`));
|
|
42
|
+
if (data.threadId) {
|
|
43
|
+
parts.push(this.dim(`thread:${data.threadId.slice(0, 8)}`));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (this.config.level === "verbose") {
|
|
47
|
+
parts.push(`
|
|
48
|
+
${this.dim("Message:")} ${this.truncate(data.message, 100)}`);
|
|
49
|
+
}
|
|
50
|
+
console.log(parts.join(" "));
|
|
51
|
+
}
|
|
52
|
+
async trackResponse(data) {
|
|
53
|
+
this.responseCount++;
|
|
54
|
+
this.totalLatency += data.latency;
|
|
55
|
+
this.totalTokens += data.tokensUsed || 0;
|
|
56
|
+
if (!this.config.logResponses) return;
|
|
57
|
+
const parts = [];
|
|
58
|
+
if (this.config.timestamps) {
|
|
59
|
+
parts.push(this.dim(`[${this.formatTime(data.timestamp)}]`));
|
|
60
|
+
}
|
|
61
|
+
parts.push(this.config.prefix);
|
|
62
|
+
parts.push(this.green("\u2190 Response"));
|
|
63
|
+
const latencyColor = data.latency < 500 ? "green" : data.latency < 2e3 ? "yellow" : "red";
|
|
64
|
+
parts.push(this[latencyColor](`${data.latency}ms`));
|
|
65
|
+
if (this.config.level !== "minimal" && data.tokensUsed) {
|
|
66
|
+
parts.push(this.dim(`${data.tokensUsed} tokens`));
|
|
67
|
+
}
|
|
68
|
+
if (this.config.level !== "minimal") {
|
|
69
|
+
parts.push(this.dim(`agent:${data.agentId.slice(0, 8)}`));
|
|
70
|
+
}
|
|
71
|
+
if (this.config.level === "verbose") {
|
|
72
|
+
parts.push(`
|
|
73
|
+
${this.dim("Response:")} ${this.truncate(data.response, 150)}`);
|
|
74
|
+
}
|
|
75
|
+
console.log(parts.join(" "));
|
|
76
|
+
}
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Extended Tracking (Optional)
|
|
79
|
+
// ============================================================================
|
|
80
|
+
async trackError(data) {
|
|
81
|
+
this.errorCount++;
|
|
82
|
+
if (!this.config.logErrors) return;
|
|
83
|
+
const parts = [];
|
|
84
|
+
if (this.config.timestamps) {
|
|
85
|
+
parts.push(this.dim(`[${this.formatTime(data.timestamp)}]`));
|
|
86
|
+
}
|
|
87
|
+
parts.push(this.config.prefix);
|
|
88
|
+
parts.push(this.red("x Error"));
|
|
89
|
+
parts.push(this.red(data.errorType));
|
|
90
|
+
if (this.config.level !== "minimal") {
|
|
91
|
+
parts.push(this.dim(`agent:${data.agentId.slice(0, 8)}`));
|
|
92
|
+
}
|
|
93
|
+
if (this.config.level === "verbose") {
|
|
94
|
+
parts.push(`
|
|
95
|
+
${this.dim("Message:")} ${data.errorMessage}`);
|
|
96
|
+
}
|
|
97
|
+
console.log(parts.join(" "));
|
|
98
|
+
}
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Summary
|
|
101
|
+
// ============================================================================
|
|
102
|
+
printSummary() {
|
|
103
|
+
const avgLatency = this.responseCount > 0 ? Math.round(this.totalLatency / this.responseCount) : 0;
|
|
104
|
+
const avgTokens = this.responseCount > 0 ? Math.round(this.totalTokens / this.responseCount) : 0;
|
|
105
|
+
console.log("");
|
|
106
|
+
console.log(this.bold(`${this.config.prefix} Summary`));
|
|
107
|
+
console.log(this.dim("\u2500".repeat(40)));
|
|
108
|
+
console.log(` Requests: ${this.cyan(this.requestCount.toString())}`);
|
|
109
|
+
console.log(` Responses: ${this.green(this.responseCount.toString())}`);
|
|
110
|
+
console.log(` Errors: ${this.errorCount > 0 ? this.red(this.errorCount.toString()) : this.dim("0")}`);
|
|
111
|
+
console.log(` Avg Latency: ${this.formatLatency(avgLatency)}`);
|
|
112
|
+
console.log(` Avg Tokens: ${this.dim(avgTokens.toString())}`);
|
|
113
|
+
console.log(` Total Tokens: ${this.dim(this.totalTokens.toString())}`);
|
|
114
|
+
console.log(this.dim("\u2500".repeat(40)));
|
|
115
|
+
console.log("");
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Reset counters
|
|
119
|
+
*/
|
|
120
|
+
reset() {
|
|
121
|
+
this.requestCount = 0;
|
|
122
|
+
this.responseCount = 0;
|
|
123
|
+
this.errorCount = 0;
|
|
124
|
+
this.totalLatency = 0;
|
|
125
|
+
this.totalTokens = 0;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get current stats
|
|
129
|
+
*/
|
|
130
|
+
getStats() {
|
|
131
|
+
return {
|
|
132
|
+
requests: this.requestCount,
|
|
133
|
+
responses: this.responseCount,
|
|
134
|
+
errors: this.errorCount,
|
|
135
|
+
avgLatency: this.responseCount > 0 ? Math.round(this.totalLatency / this.responseCount) : 0,
|
|
136
|
+
totalTokens: this.totalTokens
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Stop summary timer
|
|
141
|
+
*/
|
|
142
|
+
destroy() {
|
|
143
|
+
if (this.summaryTimer) {
|
|
144
|
+
clearInterval(this.summaryTimer);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Formatting Helpers
|
|
149
|
+
// ============================================================================
|
|
150
|
+
formatTime(date) {
|
|
151
|
+
return date.toISOString().slice(11, 23);
|
|
152
|
+
}
|
|
153
|
+
truncate(str, maxLen) {
|
|
154
|
+
const cleaned = str.replace(/\n/g, " ").trim();
|
|
155
|
+
if (cleaned.length <= maxLen) return cleaned;
|
|
156
|
+
return cleaned.slice(0, maxLen - 3) + "...";
|
|
157
|
+
}
|
|
158
|
+
formatLatency(ms) {
|
|
159
|
+
if (ms < 500) return this.green(`${ms}ms`);
|
|
160
|
+
if (ms < 2e3) return this.yellow(`${ms}ms`);
|
|
161
|
+
return this.red(`${ms}ms`);
|
|
162
|
+
}
|
|
163
|
+
// ============================================================================
|
|
164
|
+
// Color Helpers
|
|
165
|
+
// ============================================================================
|
|
166
|
+
bold(text) {
|
|
167
|
+
return this.config.colors ? `\x1B[1m${text}\x1B[0m` : text;
|
|
168
|
+
}
|
|
169
|
+
dim(text) {
|
|
170
|
+
return this.config.colors ? `\x1B[2m${text}\x1B[0m` : text;
|
|
171
|
+
}
|
|
172
|
+
green(text) {
|
|
173
|
+
return this.config.colors ? `\x1B[32m${text}\x1B[0m` : text;
|
|
174
|
+
}
|
|
175
|
+
yellow(text) {
|
|
176
|
+
return this.config.colors ? `\x1B[33m${text}\x1B[0m` : text;
|
|
177
|
+
}
|
|
178
|
+
red(text) {
|
|
179
|
+
return this.config.colors ? `\x1B[31m${text}\x1B[0m` : text;
|
|
180
|
+
}
|
|
181
|
+
cyan(text) {
|
|
182
|
+
return this.config.colors ? `\x1B[36m${text}\x1B[0m` : text;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
export {
|
|
186
|
+
ConsoleAnalytics
|
|
187
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@snap-agent/analytics-console",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Console analytics plugin for SnapAgent SDK - Pretty-print metrics to terminal for debugging",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
22
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"snap-agent",
|
|
29
|
+
"analytics",
|
|
30
|
+
"console",
|
|
31
|
+
"debugging",
|
|
32
|
+
"logging",
|
|
33
|
+
"metrics"
|
|
34
|
+
],
|
|
35
|
+
"author": "ViloTech",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@snap-agent/core": "^0.1.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^24.0.0",
|
|
45
|
+
"tsup": "^8.0.0",
|
|
46
|
+
"typescript": "^5.8.0",
|
|
47
|
+
"vitest": "^3.2.4"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/vilo-hq/snap-agent.git",
|
|
52
|
+
"directory": "plugins/analytics/console"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/vilo-hq/snap-agent/tree/main/plugins/analytics/console",
|
|
55
|
+
"bugs": {
|
|
56
|
+
"url": "https://github.com/vilo-hq/snap-agent/issues"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|