@poolzin/pool-bot 2026.1.32 → 2026.1.34

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.1.32",
3
- "commit": "6872480de072314e610d35042267561672a5b97a",
4
- "builtAt": "2026-02-04T15:55:30.791Z"
2
+ "version": "2026.1.34",
3
+ "commit": "84710f9a55bc3eca77fd7ffa882d9f11b9f92acc",
4
+ "builtAt": "2026-02-05T14:57:54.102Z"
5
5
  }
@@ -24,8 +24,6 @@ defaultOnSessionStart, defaultOnSessionEnd, registerDefaultHooks,
24
24
  clearAllHooks, } from "./lifecycle-hooks.js";
25
25
  // Integration with agent events
26
26
  export { startLifecycleHooksIntegration, getIntegrationStats, isSessionTracked, getTrackedSessionInfo, clearTrackedSessions, removeTrackedSession, } from "./lifecycle-hooks-integration.js";
27
- // Tool usage capture (Day 2 - ACTIVE, feature-flagged)
28
- export { toolUsageCaptureHook, loadSessionToolUsage, saveSessionToolUsage, } from "./tool-usage-capture.js";
29
27
  // Progressive disclosure (Day 3 - ACTIVE, feature-flagged, OPT-IN)
30
28
  // Feature flag: PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED = false (OFF by default)
31
29
  // Safe: Returns error "feature disabled" if called without enabling flag
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poolzin/pool-bot",
3
- "version": "2026.1.32",
3
+ "version": "2026.1.34",
4
4
  "description": "🎱 Pool Bot - AI assistant with PLCODE integrations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,253 +0,0 @@
1
- /**
2
- * Tool Usage Capture Hook
3
- *
4
- * Captures tool usage automatically via lifecycle hooks.
5
- * Safe: never throws, async operations, feature-flagged.
6
- *
7
- * Integration:
8
- * - Registers as onToolUse hook
9
- * - Captures all tool calls automatically
10
- * - Stores compressed data in SessionEntry
11
- */
12
- import { TOOL_USAGE_ENABLED, TOOL_USAGE_MAX_RECORDS, createToolUsageRecord, updateToolStats, addToHistory, } from "./tool-usage-storage.js";
13
- // ============================================================================
14
- // Configuration
15
- // ============================================================================
16
- const TOOL_USAGE_BUFFER_FLUSH_INTERVAL = 30000; // 30 seconds
17
- const TOOL_USAGE_BUFFER_MAX_SIZE = 50; // Flush after 50 tool calls
18
- const toolUsageBuffer = new Map();
19
- let bufferFlushScheduled = false;
20
- // ============================================================================
21
- // SessionEntry Extension (Type-safe, backward compatible)
22
- // ============================================================================
23
- /**
24
- * Load tool usage from SessionEntry
25
- * Safe: handles missing data, validates structure
26
- */
27
- export async function loadSessionToolUsage(sessionKey) {
28
- try {
29
- // TODO: Integrate with actual SessionEntry in Phase 4
30
- // For now, return in-memory placeholder
31
- const existing = toolUsageBuffer.get(sessionKey);
32
- if (existing && existing.length > 0) {
33
- // Return computed stats from buffer
34
- const tools = {};
35
- for (const record of existing) {
36
- if (!tools[record.toolName]) {
37
- tools[record.toolName] = {
38
- count: 0,
39
- totalMs: 0,
40
- avgMs: 0,
41
- lastUsed: record.timestamp,
42
- };
43
- }
44
- tools[record.toolName] = updateToolStats(tools[record.toolName], record.executionTimeMs);
45
- }
46
- return {
47
- version: 2,
48
- sessionKey,
49
- sessionId: sessionKey, // Placeholder
50
- tools,
51
- history: existing,
52
- lastCaptured: Date.now(),
53
- };
54
- }
55
- // Return empty usage
56
- return {
57
- version: 2,
58
- sessionKey,
59
- sessionId: sessionKey,
60
- tools: {},
61
- history: [],
62
- lastCaptured: Date.now(),
63
- };
64
- }
65
- catch (err) {
66
- console.error("[tool-usage-capture] Failed to load tool usage:", err);
67
- // Return empty usage on error
68
- return {
69
- version: 2,
70
- sessionKey,
71
- sessionId: sessionKey,
72
- tools: {},
73
- history: [],
74
- lastCaptured: Date.now(),
75
- };
76
- }
77
- }
78
- /**
79
- * Save tool usage to SessionEntry
80
- * Safe: validates data, handles errors gracefully
81
- */
82
- export async function saveSessionToolUsage(sessionKey, usage) {
83
- try {
84
- // TODO: Integrate with actual SessionEntry in Phase 4
85
- // For now, just update in-memory buffer
86
- const existing = toolUsageBuffer.get(sessionKey) || [];
87
- const newRecords = usage.history.slice(existing.length);
88
- if (newRecords.length > 0) {
89
- toolUsageBuffer.set(sessionKey, [...existing, ...newRecords]);
90
- }
91
- if (TOOL_USAGE_ENABLED) {
92
- console.log(`[tool-usage-capture] Saved ${newRecords.length} records for ${sessionKey}`);
93
- }
94
- }
95
- catch (err) {
96
- console.error("[tool-usage-capture] Failed to save tool usage:", err);
97
- // Never throw - errors are logged only
98
- }
99
- }
100
- // ============================================================================
101
- // Hook Implementation
102
- // ============================================================================
103
- /**
104
- * Main hook: captures tool usage automatically
105
- * Safe: validates all inputs, never throws, handles all edge cases
106
- */
107
- export const toolUsageCaptureHook = async (ctx) => {
108
- // Feature flag check (safe exit)
109
- if (!TOOL_USAGE_ENABLED) {
110
- return;
111
- }
112
- try {
113
- // Validate inputs (safe defaults)
114
- const toolName = ctx.toolName || "unknown_tool";
115
- const executionTimeMs = ctx.executionTimeMs || 0;
116
- const success = ctx.success !== undefined ? ctx.success : true;
117
- // Create compressed record
118
- const record = createToolUsageRecord(toolName, ctx.toolInput, ctx.toolOutput, executionTimeMs, success, ctx.error);
119
- // Load existing usage
120
- const usage = await loadSessionToolUsage(ctx.sessionKey);
121
- // Update stats
122
- if (!usage.tools[toolName]) {
123
- usage.tools[toolName] = {
124
- count: 0,
125
- totalMs: 0,
126
- avgMs: 0,
127
- lastUsed: record.timestamp,
128
- };
129
- }
130
- usage.tools[toolName] = updateToolStats(usage.tools[toolName], executionTimeMs);
131
- // Add to history (respects max limit)
132
- usage.history = addToHistory(usage.history, record, TOOL_USAGE_MAX_RECORDS);
133
- usage.lastCaptured = Date.now();
134
- // Save (async, non-blocking)
135
- await saveSessionToolUsage(ctx.sessionKey, usage).catch((err) => {
136
- // Save errors are logged in saveSessionToolUsage
137
- // This catch is just for extra safety
138
- console.error("[tool-usage-capture] Unhandled save error:", err);
139
- });
140
- // Debug logging (can be disabled)
141
- if (success && TOOL_USAGE_ENABLED) {
142
- console.log(`[tool-usage-capture] ${toolName} (${executionTimeMs}ms) - ${ctx.sessionKey}`);
143
- }
144
- }
145
- catch (err) {
146
- // NEVER throw from hook - would break the tool call
147
- console.error("[tool-usage-capture] Hook error:", err);
148
- }
149
- };
150
- // ============================================================================
151
- // Buffer Management (performance optimization)
152
- // ============================================================================
153
- /**
154
- * Flush in-memory buffer to storage
155
- * Safe: handles errors, never throws
156
- */
157
- export async function flushToolUsageBuffer() {
158
- try {
159
- if (toolUsageBuffer.size === 0) {
160
- return; // Nothing to flush
161
- }
162
- let flushed = 0;
163
- for (const [sessionKey, records] of toolUsageBuffer.entries()) {
164
- try {
165
- // TODO: Actually persist to SessionEntry in Phase 4
166
- // For now, buffer stays in-memory
167
- flushed += records.length;
168
- }
169
- catch (err) {
170
- console.error(`[tool-usage-capture] Failed to flush buffer for ${sessionKey}:`, err);
171
- }
172
- }
173
- if (flushed > 0 && TOOL_USAGE_ENABLED) {
174
- console.log(`[tool-usage-capture] Flushed ${flushed} records from buffer`);
175
- }
176
- }
177
- catch (err) {
178
- console.error("[tool-usage-capture] Buffer flush error:", err);
179
- }
180
- }
181
- /**
182
- * Schedule buffer flush
183
- * Safe: debounced, only schedules once
184
- */
185
- function scheduleBufferFlush() {
186
- if (bufferFlushScheduled) {
187
- return; // Already scheduled
188
- }
189
- bufferFlushScheduled = true;
190
- // Flush after 30 seconds
191
- setTimeout(async () => {
192
- await flushToolUsageBuffer();
193
- bufferFlushScheduled = false;
194
- }, TOOL_USAGE_BUFFER_FLUSH_INTERVAL);
195
- }
196
- // ============================================================================
197
- // Query API (for future use)
198
- // ============================================================================
199
- /**
200
- * Get tool usage statistics for a session
201
- * Safe: returns empty object if no data
202
- */
203
- export async function getSessionToolUsage(sessionKey) {
204
- try {
205
- const usage = await loadSessionToolUsage(sessionKey);
206
- return usage;
207
- }
208
- catch (err) {
209
- console.error(`[tool-usage-capture] Failed to get usage for ${sessionKey}:`, err);
210
- return undefined;
211
- }
212
- }
213
- /**
214
- * Get recent tool usage (last N records)
215
- * Safe: returns empty array if no data
216
- */
217
- export async function getRecentToolUsage(sessionKey, count = 10) {
218
- try {
219
- const usage = await loadSessionToolUsage(sessionKey);
220
- return usage.history.slice(-count);
221
- }
222
- catch (err) {
223
- console.error(`[tool-usage-capture] Failed to get recent usage for ${sessionKey}:`, err);
224
- return [];
225
- }
226
- }
227
- // ============================================================================
228
- // Cleanup
229
- // ============================================================================
230
- /**
231
- * Clear tool usage buffer (for testing)
232
- * Safe: never throws
233
- */
234
- export function clearToolUsageBuffer() {
235
- try {
236
- toolUsageBuffer.clear();
237
- }
238
- catch (err) {
239
- console.error("[tool-usage-capture] Buffer clear error:", err);
240
- }
241
- }
242
- /**
243
- * Clear tool usage for a specific session
244
- * Safe: never throws
245
- */
246
- export function clearSessionToolUsage(sessionKey) {
247
- try {
248
- toolUsageBuffer.delete(sessionKey);
249
- }
250
- catch (err) {
251
- console.error(`[tool-usage-capture] Failed to clear usage for ${sessionKey}:`, err);
252
- }
253
- }
@@ -1,144 +0,0 @@
1
- /**
2
- * Tool Usage Capture - Storage Layer
3
- *
4
- * Safe, efficient storage for tool usage data.
5
- * Phase 2a: Type definitions and interfaces (NO breaking changes)
6
- *
7
- * Safety measures:
8
- * - All fields optional (backward compatible)
9
- * - Version field for future migrations
10
- * - No modifications to existing SessionEntry fields
11
- */
12
- // ============================================================================
13
- // Constants
14
- // ============================================================================
15
- export const TOOL_USAGE_MAX_RECORDS = 100; // Keep only last 100 records
16
- export const TOOL_USAGE_MAX_SUMMARY_LEN = 100; // Max 100 chars per summary
17
- export const TOOL_USAGE_ENABLED = true; // Feature flag (master switch)
18
- // ============================================================================
19
- // Compression Functions (safe, no side effects)
20
- // ============================================================================
21
- /**
22
- * Compress a tool input/output value to a short summary
23
- * Safe: never throws, handles all types gracefully
24
- */
25
- export function compressToolValue(value, maxLen = TOOL_USAGE_MAX_SUMMARY_LEN) {
26
- try {
27
- // Handle primitives
28
- if (value === null)
29
- return "null";
30
- if (value === undefined)
31
- return "undefined";
32
- if (typeof value === "string") {
33
- return value.length > maxLen ? value.slice(0, maxLen) + "..." : value;
34
- }
35
- if (typeof value === "number")
36
- return String(value);
37
- if (typeof value === "boolean")
38
- return String(value);
39
- // Handle objects and arrays
40
- if (typeof value === "object") {
41
- const json = JSON.stringify(value);
42
- return json.length > maxLen ? json.slice(0, maxLen) + "..." : json;
43
- }
44
- // Fallback
45
- return String(value);
46
- }
47
- catch (err) {
48
- // If compression fails, return safe fallback
49
- return "[compression_error]";
50
- }
51
- }
52
- /**
53
- * Create a tool usage record from hook context
54
- * Safe: validates all inputs, never throws
55
- */
56
- export function createToolUsageRecord(toolName, toolInput, toolOutput, executionTimeMs, success, error) {
57
- // Validate inputs (safe defaults)
58
- const safeToolName = typeof toolName === "string" && toolName.length > 0 ? toolName : "unknown_tool";
59
- const safeInput = typeof toolInput === "object" && toolInput !== null ? toolInput : {};
60
- const safeTime = typeof executionTimeMs === "number" && executionTimeMs >= 0 ? executionTimeMs : 0;
61
- const safeSuccess = Boolean(success);
62
- return {
63
- toolName: safeToolName,
64
- timestamp: Date.now(),
65
- executionTimeMs: safeTime,
66
- success: safeSuccess,
67
- inputSummary: compressToolValue(safeInput),
68
- outputSummary: compressToolValue(toolOutput),
69
- error: error ? String(error).slice(0, 200) : undefined,
70
- };
71
- }
72
- // ============================================================================
73
- // Statistics Update (pure function, no side effects)
74
- // ============================================================================
75
- /**
76
- * Update tool statistics with a new record
77
- * Safe: never mutates input, returns new object
78
- */
79
- export function updateToolStats(existingStats, executionTimeMs) {
80
- const count = (existingStats?.count ?? 0) + 1;
81
- const totalMs = (existingStats?.totalMs ?? 0) + executionTimeMs;
82
- const avgMs = count > 0 ? Math.round((totalMs / count) * 100) / 100 : 0;
83
- return {
84
- count,
85
- totalMs,
86
- avgMs,
87
- lastUsed: Date.now(),
88
- };
89
- }
90
- // ============================================================================
91
- // History Management (pure functions)
92
- // ============================================================================
93
- /**
94
- * Add record to history, respecting max limit
95
- * Safe: never exceeds max records, returns new array
96
- */
97
- export function addToHistory(history, record, maxRecords = TOOL_USAGE_MAX_RECORDS) {
98
- const newHistory = [...history, record];
99
- // Keep only last N records
100
- if (newHistory.length > maxRecords) {
101
- return newHistory.slice(-maxRecords);
102
- }
103
- return newHistory;
104
- }
105
- /**
106
- * Get recent tool usage (last N records)
107
- * Safe: never mutates input, returns slice
108
- */
109
- export function getRecentToolUsage(history, count = 10) {
110
- return history.slice(-count);
111
- }
112
- // ============================================================================
113
- // Query Functions (for future use)
114
- // ============================================================================
115
- /**
116
- * Get statistics for a specific tool
117
- * Safe: returns undefined if tool not found
118
- */
119
- export function getToolStats(usage, toolName) {
120
- return usage?.tools[toolName];
121
- }
122
- /**
123
- * Get all tool names sorted by usage frequency
124
- * Safe: returns empty array if no data
125
- */
126
- export function getToolsByFrequency(usage) {
127
- if (!usage?.tools)
128
- return [];
129
- return Object.entries(usage.tools)
130
- .map(([toolName, stats]) => ({ toolName, count: stats.count }))
131
- .sort((a, b) => b.count - a.count);
132
- }
133
- /**
134
- * Get slowest tools (by average execution time)
135
- * Safe: returns empty array if no data
136
- */
137
- export function getSlowestTools(usage, limit = 5) {
138
- if (!usage?.tools)
139
- return [];
140
- return Object.entries(usage.tools)
141
- .map(([toolName, stats]) => ({ toolName, avgMs: stats.avgMs }))
142
- .sort((a, b) => b.avgMs - a.avgMs)
143
- .slice(0, limit);
144
- }