olympus-ai 3.2.3 → 3.3.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/.claude-plugin/plugin.json +1 -1
- package/dist/__tests__/ascent-checkpoint.test.d.ts +2 -0
- package/dist/__tests__/ascent-checkpoint.test.d.ts.map +1 -0
- package/dist/__tests__/ascent-checkpoint.test.js +261 -0
- package/dist/__tests__/ascent-checkpoint.test.js.map +1 -0
- package/dist/__tests__/config-ascent.test.d.ts +2 -0
- package/dist/__tests__/config-ascent.test.d.ts.map +1 -0
- package/dist/__tests__/config-ascent.test.js +134 -0
- package/dist/__tests__/config-ascent.test.js.map +1 -0
- package/dist/__tests__/hook-blocking.test.d.ts +8 -0
- package/dist/__tests__/hook-blocking.test.d.ts.map +1 -0
- package/dist/__tests__/hook-blocking.test.js +277 -0
- package/dist/__tests__/hook-blocking.test.js.map +1 -0
- package/dist/__tests__/installer.test.js +1 -1
- package/dist/__tests__/metrics-cli.test.d.ts +5 -0
- package/dist/__tests__/metrics-cli.test.d.ts.map +1 -0
- package/dist/__tests__/metrics-cli.test.js +24 -0
- package/dist/__tests__/metrics-cli.test.js.map +1 -0
- package/dist/__tests__/skill-auto-detection.test.d.ts +2 -0
- package/dist/__tests__/skill-auto-detection.test.d.ts.map +1 -0
- package/dist/__tests__/skill-auto-detection.test.js +255 -0
- package/dist/__tests__/skill-auto-detection.test.js.map +1 -0
- package/dist/__tests__/token-estimator.test.d.ts +5 -0
- package/dist/__tests__/token-estimator.test.d.ts.map +1 -0
- package/dist/__tests__/token-estimator.test.js +192 -0
- package/dist/__tests__/token-estimator.test.js.map +1 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +83 -1
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/document-writer.d.ts.map +1 -1
- package/dist/agents/document-writer.js +38 -0
- package/dist/agents/document-writer.js.map +1 -1
- package/dist/agents/frontend-engineer.d.ts.map +1 -1
- package/dist/agents/frontend-engineer.js +16 -0
- package/dist/agents/frontend-engineer.js.map +1 -1
- package/dist/agents/olympian.d.ts.map +1 -1
- package/dist/agents/olympian.js +15 -0
- package/dist/agents/olympian.js.map +1 -1
- package/dist/cli/commands/metrics.d.ts +31 -0
- package/dist/cli/commands/metrics.d.ts.map +1 -0
- package/dist/cli/commands/metrics.js +266 -0
- package/dist/cli/commands/metrics.js.map +1 -0
- package/dist/cli/index.js +39 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +16 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/features/ascent-checkpoint/index.d.ts +48 -0
- package/dist/features/ascent-checkpoint/index.d.ts.map +1 -0
- package/dist/features/ascent-checkpoint/index.js +144 -0
- package/dist/features/ascent-checkpoint/index.js.map +1 -0
- package/dist/features/hook-logging/index.d.ts +37 -0
- package/dist/features/hook-logging/index.d.ts.map +1 -0
- package/dist/features/hook-logging/index.js +120 -0
- package/dist/features/hook-logging/index.js.map +1 -0
- package/dist/features/hook-logging/index.test.d.ts +5 -0
- package/dist/features/hook-logging/index.test.d.ts.map +1 -0
- package/dist/features/hook-logging/index.test.js +268 -0
- package/dist/features/hook-logging/index.test.js.map +1 -0
- package/dist/features/index.d.ts +3 -0
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +8 -0
- package/dist/features/index.js.map +1 -1
- package/dist/features/magic-keywords.d.ts +51 -0
- package/dist/features/magic-keywords.d.ts.map +1 -1
- package/dist/features/magic-keywords.js +172 -0
- package/dist/features/magic-keywords.js.map +1 -1
- package/dist/features/session-state/index.d.ts +50 -0
- package/dist/features/session-state/index.d.ts.map +1 -0
- package/dist/features/session-state/index.js +64 -0
- package/dist/features/session-state/index.js.map +1 -0
- package/dist/features/session-state/index.test.d.ts +5 -0
- package/dist/features/session-state/index.test.d.ts.map +1 -0
- package/dist/features/session-state/index.test.js +221 -0
- package/dist/features/session-state/index.test.js.map +1 -0
- package/dist/features/token-metrics/index.d.ts +6 -0
- package/dist/features/token-metrics/index.d.ts.map +1 -0
- package/dist/features/token-metrics/index.js +5 -0
- package/dist/features/token-metrics/index.js.map +1 -0
- package/dist/features/token-metrics/storage.d.ts +16 -0
- package/dist/features/token-metrics/storage.d.ts.map +1 -0
- package/dist/features/token-metrics/storage.js +144 -0
- package/dist/features/token-metrics/storage.js.map +1 -0
- package/dist/features/token-metrics/token-estimator.d.ts +66 -0
- package/dist/features/token-metrics/token-estimator.d.ts.map +1 -0
- package/dist/features/token-metrics/token-estimator.js +230 -0
- package/dist/features/token-metrics/token-estimator.js.map +1 -0
- package/dist/features/token-metrics/types.d.ts +63 -0
- package/dist/features/token-metrics/types.d.ts.map +1 -0
- package/dist/features/token-metrics/types.js +5 -0
- package/dist/features/token-metrics/types.js.map +1 -0
- package/dist/hooks/olympus-orchestrator/constants.d.ts +2 -0
- package/dist/hooks/olympus-orchestrator/constants.d.ts.map +1 -1
- package/dist/hooks/olympus-orchestrator/constants.js +41 -0
- package/dist/hooks/olympus-orchestrator/constants.js.map +1 -1
- package/dist/hooks/olympus-orchestrator/index.d.ts +10 -1
- package/dist/hooks/olympus-orchestrator/index.d.ts.map +1 -1
- package/dist/hooks/olympus-orchestrator/index.js +108 -14
- package/dist/hooks/olympus-orchestrator/index.js.map +1 -1
- package/dist/hooks/registrations/index.d.ts +2 -1
- package/dist/hooks/registrations/index.d.ts.map +1 -1
- package/dist/hooks/registrations/index.js +3 -1
- package/dist/hooks/registrations/index.js.map +1 -1
- package/dist/hooks/registrations/token-metrics.d.ts +11 -0
- package/dist/hooks/registrations/token-metrics.d.ts.map +1 -0
- package/dist/hooks/registrations/token-metrics.js +119 -0
- package/dist/hooks/registrations/token-metrics.js.map +1 -0
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +334 -9
- package/dist/installer/index.js.map +1 -1
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/scripts/.olympus/token-metrics.jsonl +1 -0
- package/scripts/dist/hooks/olympus-hooks.cjs +127 -128
- package/scripts/esbuild.hooks.mjs +1 -1
- package/.claude/CLAUDE.md +0 -66
- package/scripts/generate-logo-hybrid-v2.mjs +0 -213
- package/scripts/generate-logo-hybrid.mjs +0 -209
- package/scripts/generate-logo-infinity.mjs +0 -239
- package/scripts/generate-logo-mythology.mjs +0 -190
- package/scripts/generate-logo-orchestration.mjs +0 -228
- package/scripts/generate-logo-recraft.mjs +0 -147
- package/scripts/generate-logo-simple.mjs +0 -154
- package/scripts/generate-logo.mjs +0 -117
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Session State Tracking
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
5
|
+
import { SessionState } from './index.js';
|
|
6
|
+
describe('SessionState', () => {
|
|
7
|
+
let state;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
state = new SessionState();
|
|
10
|
+
});
|
|
11
|
+
describe('recordTaskCompletion', () => {
|
|
12
|
+
it('should record a single task completion', () => {
|
|
13
|
+
const completion = {
|
|
14
|
+
timestamp: Date.now(),
|
|
15
|
+
filesModified: ['src/index.ts'],
|
|
16
|
+
taskId: 'task-1',
|
|
17
|
+
};
|
|
18
|
+
state.recordTaskCompletion(completion);
|
|
19
|
+
expect(state.trackedCount).toBe(1);
|
|
20
|
+
expect(state.getRecentTasks()).toEqual([completion]);
|
|
21
|
+
});
|
|
22
|
+
it('should record multiple task completions', () => {
|
|
23
|
+
const completion1 = {
|
|
24
|
+
timestamp: Date.now(),
|
|
25
|
+
filesModified: ['src/index.ts'],
|
|
26
|
+
taskId: 'task-1',
|
|
27
|
+
};
|
|
28
|
+
const completion2 = {
|
|
29
|
+
timestamp: Date.now() + 1000,
|
|
30
|
+
filesModified: ['src/utils.ts'],
|
|
31
|
+
taskId: 'task-2',
|
|
32
|
+
};
|
|
33
|
+
state.recordTaskCompletion(completion1);
|
|
34
|
+
state.recordTaskCompletion(completion2);
|
|
35
|
+
expect(state.trackedCount).toBe(2);
|
|
36
|
+
expect(state.getRecentTasks()).toEqual([completion2, completion1]);
|
|
37
|
+
});
|
|
38
|
+
it('should maintain maximum of 3 tasks', () => {
|
|
39
|
+
const tasks = [
|
|
40
|
+
{ timestamp: 1, filesModified: ['file1.ts'], taskId: 'task-1' },
|
|
41
|
+
{ timestamp: 2, filesModified: ['file2.ts'], taskId: 'task-2' },
|
|
42
|
+
{ timestamp: 3, filesModified: ['file3.ts'], taskId: 'task-3' },
|
|
43
|
+
{ timestamp: 4, filesModified: ['file4.ts'], taskId: 'task-4' },
|
|
44
|
+
];
|
|
45
|
+
for (const task of tasks) {
|
|
46
|
+
state.recordTaskCompletion(task);
|
|
47
|
+
}
|
|
48
|
+
expect(state.trackedCount).toBe(3);
|
|
49
|
+
const recent = state.getRecentTasks();
|
|
50
|
+
expect(recent).toHaveLength(3);
|
|
51
|
+
expect(recent[0].taskId).toBe('task-4'); // Most recent
|
|
52
|
+
expect(recent[1].taskId).toBe('task-3');
|
|
53
|
+
expect(recent[2].taskId).toBe('task-2');
|
|
54
|
+
// task-1 should be evicted
|
|
55
|
+
});
|
|
56
|
+
it('should add new tasks to the front', () => {
|
|
57
|
+
const task1 = {
|
|
58
|
+
timestamp: 1,
|
|
59
|
+
filesModified: ['file1.ts'],
|
|
60
|
+
taskId: 'task-1',
|
|
61
|
+
};
|
|
62
|
+
const task2 = {
|
|
63
|
+
timestamp: 2,
|
|
64
|
+
filesModified: ['file2.ts'],
|
|
65
|
+
taskId: 'task-2',
|
|
66
|
+
};
|
|
67
|
+
state.recordTaskCompletion(task1);
|
|
68
|
+
state.recordTaskCompletion(task2);
|
|
69
|
+
const recent = state.getRecentTasks();
|
|
70
|
+
expect(recent[0]).toEqual(task2); // Most recent first
|
|
71
|
+
expect(recent[1]).toEqual(task1);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('isVerificationEdit', () => {
|
|
75
|
+
beforeEach(() => {
|
|
76
|
+
state.recordTaskCompletion({
|
|
77
|
+
timestamp: Date.now(),
|
|
78
|
+
filesModified: ['src/index.ts', 'src/utils.ts'],
|
|
79
|
+
taskId: 'task-1',
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
it('should return true for small edit on recent task file', () => {
|
|
83
|
+
expect(state.isVerificationEdit('src/index.ts', 5)).toBe(true);
|
|
84
|
+
expect(state.isVerificationEdit('src/utils.ts', 9)).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
it('should return false for large edit on recent task file', () => {
|
|
87
|
+
expect(state.isVerificationEdit('src/index.ts', 10)).toBe(false);
|
|
88
|
+
expect(state.isVerificationEdit('src/index.ts', 100)).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
it('should return false for small edit on non-recent file', () => {
|
|
91
|
+
expect(state.isVerificationEdit('src/other.ts', 5)).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
it('should return false for file not modified by any task', () => {
|
|
94
|
+
expect(state.isVerificationEdit('new-file.ts', 3)).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
it('should check across multiple recent tasks', () => {
|
|
97
|
+
state.recordTaskCompletion({
|
|
98
|
+
timestamp: Date.now() + 1000,
|
|
99
|
+
filesModified: ['src/components.ts'],
|
|
100
|
+
taskId: 'task-2',
|
|
101
|
+
});
|
|
102
|
+
state.recordTaskCompletion({
|
|
103
|
+
timestamp: Date.now() + 2000,
|
|
104
|
+
filesModified: ['src/hooks.ts'],
|
|
105
|
+
taskId: 'task-3',
|
|
106
|
+
});
|
|
107
|
+
// All files from last 3 tasks should be considered
|
|
108
|
+
expect(state.isVerificationEdit('src/hooks.ts', 5)).toBe(true);
|
|
109
|
+
expect(state.isVerificationEdit('src/components.ts', 5)).toBe(true);
|
|
110
|
+
expect(state.isVerificationEdit('src/index.ts', 5)).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
it('should not consider files from evicted tasks', () => {
|
|
113
|
+
// Add 3 more tasks, pushing task-1 out
|
|
114
|
+
state.recordTaskCompletion({
|
|
115
|
+
timestamp: Date.now() + 1000,
|
|
116
|
+
filesModified: ['file2.ts'],
|
|
117
|
+
taskId: 'task-2',
|
|
118
|
+
});
|
|
119
|
+
state.recordTaskCompletion({
|
|
120
|
+
timestamp: Date.now() + 2000,
|
|
121
|
+
filesModified: ['file3.ts'],
|
|
122
|
+
taskId: 'task-3',
|
|
123
|
+
});
|
|
124
|
+
state.recordTaskCompletion({
|
|
125
|
+
timestamp: Date.now() + 3000,
|
|
126
|
+
filesModified: ['file4.ts'],
|
|
127
|
+
taskId: 'task-4',
|
|
128
|
+
});
|
|
129
|
+
// Original files should no longer be considered
|
|
130
|
+
expect(state.isVerificationEdit('src/index.ts', 5)).toBe(false);
|
|
131
|
+
expect(state.isVerificationEdit('src/utils.ts', 5)).toBe(false);
|
|
132
|
+
// New files should be considered
|
|
133
|
+
expect(state.isVerificationEdit('file2.ts', 5)).toBe(true);
|
|
134
|
+
expect(state.isVerificationEdit('file3.ts', 5)).toBe(true);
|
|
135
|
+
expect(state.isVerificationEdit('file4.ts', 5)).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
it('should handle boundary case of exactly 10 lines', () => {
|
|
138
|
+
expect(state.isVerificationEdit('src/index.ts', 9)).toBe(true);
|
|
139
|
+
expect(state.isVerificationEdit('src/index.ts', 10)).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('getRecentTaskFiles', () => {
|
|
143
|
+
it('should return empty array when no tasks', () => {
|
|
144
|
+
expect(state.getRecentTaskFiles()).toEqual([]);
|
|
145
|
+
});
|
|
146
|
+
it('should return files from single task', () => {
|
|
147
|
+
state.recordTaskCompletion({
|
|
148
|
+
timestamp: Date.now(),
|
|
149
|
+
filesModified: ['file1.ts', 'file2.ts'],
|
|
150
|
+
taskId: 'task-1',
|
|
151
|
+
});
|
|
152
|
+
const files = state.getRecentTaskFiles();
|
|
153
|
+
expect(files).toContain('file1.ts');
|
|
154
|
+
expect(files).toContain('file2.ts');
|
|
155
|
+
});
|
|
156
|
+
it('should return deduplicated files from multiple tasks', () => {
|
|
157
|
+
state.recordTaskCompletion({
|
|
158
|
+
timestamp: 1,
|
|
159
|
+
filesModified: ['file1.ts', 'file2.ts'],
|
|
160
|
+
taskId: 'task-1',
|
|
161
|
+
});
|
|
162
|
+
state.recordTaskCompletion({
|
|
163
|
+
timestamp: 2,
|
|
164
|
+
filesModified: ['file2.ts', 'file3.ts'], // file2.ts repeated
|
|
165
|
+
taskId: 'task-2',
|
|
166
|
+
});
|
|
167
|
+
const files = state.getRecentTaskFiles();
|
|
168
|
+
expect(files).toHaveLength(3);
|
|
169
|
+
expect(files).toContain('file1.ts');
|
|
170
|
+
expect(files).toContain('file2.ts');
|
|
171
|
+
expect(files).toContain('file3.ts');
|
|
172
|
+
});
|
|
173
|
+
it('should only include files from last 3 tasks', () => {
|
|
174
|
+
state.recordTaskCompletion({
|
|
175
|
+
timestamp: 1,
|
|
176
|
+
filesModified: ['old-file.ts'],
|
|
177
|
+
taskId: 'task-1',
|
|
178
|
+
});
|
|
179
|
+
state.recordTaskCompletion({
|
|
180
|
+
timestamp: 2,
|
|
181
|
+
filesModified: ['file2.ts'],
|
|
182
|
+
taskId: 'task-2',
|
|
183
|
+
});
|
|
184
|
+
state.recordTaskCompletion({
|
|
185
|
+
timestamp: 3,
|
|
186
|
+
filesModified: ['file3.ts'],
|
|
187
|
+
taskId: 'task-3',
|
|
188
|
+
});
|
|
189
|
+
state.recordTaskCompletion({
|
|
190
|
+
timestamp: 4,
|
|
191
|
+
filesModified: ['file4.ts'],
|
|
192
|
+
taskId: 'task-4',
|
|
193
|
+
});
|
|
194
|
+
const files = state.getRecentTaskFiles();
|
|
195
|
+
expect(files).not.toContain('old-file.ts');
|
|
196
|
+
expect(files).toContain('file2.ts');
|
|
197
|
+
expect(files).toContain('file3.ts');
|
|
198
|
+
expect(files).toContain('file4.ts');
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
describe('clear', () => {
|
|
202
|
+
it('should clear all tracked tasks', () => {
|
|
203
|
+
state.recordTaskCompletion({
|
|
204
|
+
timestamp: Date.now(),
|
|
205
|
+
filesModified: ['file1.ts'],
|
|
206
|
+
taskId: 'task-1',
|
|
207
|
+
});
|
|
208
|
+
state.recordTaskCompletion({
|
|
209
|
+
timestamp: Date.now(),
|
|
210
|
+
filesModified: ['file2.ts'],
|
|
211
|
+
taskId: 'task-2',
|
|
212
|
+
});
|
|
213
|
+
expect(state.trackedCount).toBe(2);
|
|
214
|
+
state.clear();
|
|
215
|
+
expect(state.trackedCount).toBe(0);
|
|
216
|
+
expect(state.getRecentTasks()).toEqual([]);
|
|
217
|
+
expect(state.getRecentTaskFiles()).toEqual([]);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/features/session-state/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token metrics system for Olympus analytics
|
|
3
|
+
*/
|
|
4
|
+
export { estimateTokens, estimateTokensDetailed, estimateTokensFromToolOutput, estimateContextSize, estimateTokensSync } from './token-estimator.js';
|
|
5
|
+
export type { TokenEstimate, ConversationMetrics } from './types.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/token-metrics/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrJ,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/token-metrics/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TokenMetricsEntry } from './types.js';
|
|
2
|
+
/** Get token metrics storage directory (project-specific) */
|
|
3
|
+
export declare function getTokenMetricsDir(projectPath: string): string;
|
|
4
|
+
/** Get token metrics archive directory */
|
|
5
|
+
export declare function getTokenMetricsArchiveDir(projectPath: string): string;
|
|
6
|
+
/** Ensure token metrics directories exist */
|
|
7
|
+
export declare function ensureTokenMetricsDirs(projectPath: string): void;
|
|
8
|
+
/** Log a token metric entry */
|
|
9
|
+
export declare function logTokenMetric(entry: TokenMetricsEntry, projectPath?: string): Promise<void>;
|
|
10
|
+
/** Read token metrics from JSONL file */
|
|
11
|
+
export declare function readTokenMetrics(projectPath?: string, limit?: number): Promise<TokenMetricsEntry[]>;
|
|
12
|
+
/** Read all token metrics including archived files */
|
|
13
|
+
export declare function readAllTokenMetrics(projectPath?: string): Promise<TokenMetricsEntry[]>;
|
|
14
|
+
/** Clean up old metrics files beyond retention period */
|
|
15
|
+
export declare function cleanupOldMetrics(daysToKeep: number, projectPath?: string): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/features/token-metrics/storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAKpD,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,0CAA0C;AAC1C,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,6CAA6C;AAC7C,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAUhE;AAwBD,+BAA+B;AAC/B,wBAAsB,cAAc,CAAC,KAAK,EAAE,iBAAiB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWlG;AAED,yCAAyC;AACzC,wBAAsB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAsBzG;AAED,sDAAsD;AACtD,wBAAsB,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAmC5F;AAED,yDAAyD;AACzD,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkC/F"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { existsSync, mkdirSync, appendFileSync, readFileSync, renameSync, readdirSync, unlinkSync, statSync } from 'fs';
|
|
3
|
+
/** Maximum lines before rotating JSONL files */
|
|
4
|
+
const MAX_JSONL_LINES = 10000;
|
|
5
|
+
/** Get token metrics storage directory (project-specific) */
|
|
6
|
+
export function getTokenMetricsDir(projectPath) {
|
|
7
|
+
return join(projectPath, '.olympus');
|
|
8
|
+
}
|
|
9
|
+
/** Get token metrics archive directory */
|
|
10
|
+
export function getTokenMetricsArchiveDir(projectPath) {
|
|
11
|
+
return join(projectPath, '.olympus', 'archives');
|
|
12
|
+
}
|
|
13
|
+
/** Ensure token metrics directories exist */
|
|
14
|
+
export function ensureTokenMetricsDirs(projectPath) {
|
|
15
|
+
const metricsDir = getTokenMetricsDir(projectPath);
|
|
16
|
+
if (!existsSync(metricsDir)) {
|
|
17
|
+
mkdirSync(metricsDir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
const archiveDir = getTokenMetricsArchiveDir(projectPath);
|
|
20
|
+
if (!existsSync(archiveDir)) {
|
|
21
|
+
mkdirSync(archiveDir, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Rotate JSONL file if it exceeds size threshold */
|
|
25
|
+
function rotateIfNeeded(filePath, projectPath, maxLines = MAX_JSONL_LINES) {
|
|
26
|
+
if (!existsSync(filePath))
|
|
27
|
+
return;
|
|
28
|
+
try {
|
|
29
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
30
|
+
const lineCount = content.split('\n').filter(l => l.trim()).length;
|
|
31
|
+
if (lineCount >= maxLines) {
|
|
32
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
33
|
+
const archiveDir = getTokenMetricsArchiveDir(projectPath);
|
|
34
|
+
const archivePath = join(archiveDir, `token-metrics-${timestamp}.jsonl`);
|
|
35
|
+
renameSync(filePath, archivePath);
|
|
36
|
+
console.log(`[Olympus Token Metrics] Archived ${lineCount} entries to ${archivePath}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error(`[Olympus Token Metrics] Failed to rotate ${filePath}:`, error);
|
|
41
|
+
// Don't throw - rotation failures should not block appending
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Log a token metric entry */
|
|
45
|
+
export async function logTokenMetric(entry, projectPath) {
|
|
46
|
+
// Use project path from entry if not provided
|
|
47
|
+
const path = projectPath || entry.project_path || process.cwd();
|
|
48
|
+
ensureTokenMetricsDirs(path);
|
|
49
|
+
const logPath = join(getTokenMetricsDir(path), 'token-metrics.jsonl');
|
|
50
|
+
// Rotate before appending
|
|
51
|
+
rotateIfNeeded(logPath, path);
|
|
52
|
+
appendFileSync(logPath, JSON.stringify(entry) + '\n', 'utf-8');
|
|
53
|
+
}
|
|
54
|
+
/** Read token metrics from JSONL file */
|
|
55
|
+
export async function readTokenMetrics(projectPath, limit) {
|
|
56
|
+
const path = projectPath || process.cwd();
|
|
57
|
+
const logPath = join(getTokenMetricsDir(path), 'token-metrics.jsonl');
|
|
58
|
+
if (!existsSync(logPath))
|
|
59
|
+
return [];
|
|
60
|
+
try {
|
|
61
|
+
const content = readFileSync(logPath, 'utf-8');
|
|
62
|
+
const entries = content
|
|
63
|
+
.split('\n')
|
|
64
|
+
.filter(line => line.trim())
|
|
65
|
+
.map(line => JSON.parse(line));
|
|
66
|
+
if (limit && limit > 0) {
|
|
67
|
+
return entries.slice(-limit); // Return last N entries
|
|
68
|
+
}
|
|
69
|
+
return entries;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error(`[Olympus Token Metrics] Failed to read ${logPath}:`, error);
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Read all token metrics including archived files */
|
|
77
|
+
export async function readAllTokenMetrics(projectPath) {
|
|
78
|
+
const path = projectPath || process.cwd();
|
|
79
|
+
const allEntries = [];
|
|
80
|
+
// Read current file
|
|
81
|
+
const currentEntries = await readTokenMetrics(path);
|
|
82
|
+
allEntries.push(...currentEntries);
|
|
83
|
+
// Read archived files
|
|
84
|
+
const archiveDir = getTokenMetricsArchiveDir(path);
|
|
85
|
+
if (existsSync(archiveDir)) {
|
|
86
|
+
try {
|
|
87
|
+
const archiveFiles = readdirSync(archiveDir)
|
|
88
|
+
.filter(f => f.startsWith('token-metrics-') && f.endsWith('.jsonl'))
|
|
89
|
+
.sort(); // Chronological order
|
|
90
|
+
for (const file of archiveFiles) {
|
|
91
|
+
const archivePath = join(archiveDir, file);
|
|
92
|
+
try {
|
|
93
|
+
const content = readFileSync(archivePath, 'utf-8');
|
|
94
|
+
const entries = content
|
|
95
|
+
.split('\n')
|
|
96
|
+
.filter(line => line.trim())
|
|
97
|
+
.map(line => JSON.parse(line));
|
|
98
|
+
allEntries.push(...entries);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error(`[Olympus Token Metrics] Failed to read archive ${file}:`, error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error(`[Olympus Token Metrics] Failed to read archive directory:`, error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return allEntries;
|
|
110
|
+
}
|
|
111
|
+
/** Clean up old metrics files beyond retention period */
|
|
112
|
+
export async function cleanupOldMetrics(daysToKeep, projectPath) {
|
|
113
|
+
const path = projectPath || process.cwd();
|
|
114
|
+
const archiveDir = getTokenMetricsArchiveDir(path);
|
|
115
|
+
if (!existsSync(archiveDir))
|
|
116
|
+
return;
|
|
117
|
+
const cutoffDate = new Date();
|
|
118
|
+
cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
|
|
119
|
+
try {
|
|
120
|
+
const archiveFiles = readdirSync(archiveDir)
|
|
121
|
+
.filter(f => f.startsWith('token-metrics-') && f.endsWith('.jsonl'));
|
|
122
|
+
let deletedCount = 0;
|
|
123
|
+
for (const file of archiveFiles) {
|
|
124
|
+
const filePath = join(archiveDir, file);
|
|
125
|
+
try {
|
|
126
|
+
const stats = statSync(filePath);
|
|
127
|
+
if (stats.mtime < cutoffDate) {
|
|
128
|
+
unlinkSync(filePath);
|
|
129
|
+
deletedCount++;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error(`[Olympus Token Metrics] Failed to process ${file}:`, error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (deletedCount > 0) {
|
|
137
|
+
console.log(`[Olympus Token Metrics] Cleaned up ${deletedCount} old archive files`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
console.error(`[Olympus Token Metrics] Failed to cleanup old metrics:`, error);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/features/token-metrics/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token estimation utilities for Olympus metrics
|
|
3
|
+
*
|
|
4
|
+
* Uses gpt-tokenizer for accurate token counting with fallback to character-based estimation.
|
|
5
|
+
* Token counts are approximations for tracking trends, not exact billing calculations.
|
|
6
|
+
*/
|
|
7
|
+
import type { TokenEstimate, ConversationMetrics } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Main token estimation function
|
|
10
|
+
*
|
|
11
|
+
* @param text - Text to estimate tokens for
|
|
12
|
+
* @returns Estimated token count
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const tokens = await estimateTokens("Hello, world!");
|
|
17
|
+
* console.log(tokens); // ~4 tokens
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function estimateTokens(text: string): Promise<number>;
|
|
21
|
+
/**
|
|
22
|
+
* Estimate tokens with detailed metadata
|
|
23
|
+
*
|
|
24
|
+
* @param input - Input to estimate (string, object, array, etc.)
|
|
25
|
+
* @returns Token estimate with method and input type
|
|
26
|
+
*/
|
|
27
|
+
export declare function estimateTokensDetailed(input: unknown): Promise<TokenEstimate>;
|
|
28
|
+
/**
|
|
29
|
+
* Estimate tokens from tool output (handles various result formats)
|
|
30
|
+
*
|
|
31
|
+
* @param output - Tool output object (from Claude Code SDK)
|
|
32
|
+
* @returns Estimated token count
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const readResult = { content: "file contents..." };
|
|
37
|
+
* const tokens = await estimateTokensFromToolOutput(readResult);
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function estimateTokensFromToolOutput(output: unknown): Promise<number>;
|
|
41
|
+
/**
|
|
42
|
+
* Estimate total context size from conversation messages
|
|
43
|
+
*
|
|
44
|
+
* @param messages - Array of message objects (any format with text content)
|
|
45
|
+
* @returns Conversation metrics with total tokens and averages
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const messages = [
|
|
50
|
+
* { role: "user", content: "Hello" },
|
|
51
|
+
* { role: "assistant", content: "Hi there!" }
|
|
52
|
+
* ];
|
|
53
|
+
* const metrics = await estimateContextSize(messages);
|
|
54
|
+
* console.log(metrics.totalTokens); // ~8 tokens
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function estimateContextSize(messages: unknown[]): Promise<ConversationMetrics>;
|
|
58
|
+
/**
|
|
59
|
+
* Synchronous version of estimateTokens using only character-based estimation
|
|
60
|
+
* Useful when async operations aren't possible
|
|
61
|
+
*
|
|
62
|
+
* @param text - Text to estimate tokens for
|
|
63
|
+
* @returns Estimated token count (character-based)
|
|
64
|
+
*/
|
|
65
|
+
export declare function estimateTokensSync(text: string): number;
|
|
66
|
+
//# sourceMappingURL=token-estimator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-estimator.d.ts","sourceRoot":"","sources":["../../../src/features/token-metrics/token-estimator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAqDrE;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBlE;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CA+BnF;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BnF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAgD3F;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvD"}
|