cost-katana-cli 2.0.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.
Files changed (148) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +343 -0
  3. package/bin/cost-katana.js +20 -0
  4. package/dist/commands/agent-inspect.d.ts +3 -0
  5. package/dist/commands/agent-inspect.d.ts.map +1 -0
  6. package/dist/commands/agent-inspect.js +630 -0
  7. package/dist/commands/agent-inspect.js.map +1 -0
  8. package/dist/commands/analytics.d.ts +3 -0
  9. package/dist/commands/analytics.d.ts.map +1 -0
  10. package/dist/commands/analytics.js +375 -0
  11. package/dist/commands/analytics.js.map +1 -0
  12. package/dist/commands/analyze.d.ts +3 -0
  13. package/dist/commands/analyze.d.ts.map +1 -0
  14. package/dist/commands/analyze.js +286 -0
  15. package/dist/commands/analyze.js.map +1 -0
  16. package/dist/commands/ask.d.ts +3 -0
  17. package/dist/commands/ask.d.ts.map +1 -0
  18. package/dist/commands/ask.js +137 -0
  19. package/dist/commands/ask.js.map +1 -0
  20. package/dist/commands/audit-firewall.d.ts +3 -0
  21. package/dist/commands/audit-firewall.d.ts.map +1 -0
  22. package/dist/commands/audit-firewall.js +737 -0
  23. package/dist/commands/audit-firewall.js.map +1 -0
  24. package/dist/commands/budget.d.ts +3 -0
  25. package/dist/commands/budget.d.ts.map +1 -0
  26. package/dist/commands/budget.js +283 -0
  27. package/dist/commands/budget.js.map +1 -0
  28. package/dist/commands/bulk-optimize.d.ts +3 -0
  29. package/dist/commands/bulk-optimize.d.ts.map +1 -0
  30. package/dist/commands/bulk-optimize.js +863 -0
  31. package/dist/commands/bulk-optimize.js.map +1 -0
  32. package/dist/commands/chat.d.ts +3 -0
  33. package/dist/commands/chat.d.ts.map +1 -0
  34. package/dist/commands/chat.js +292 -0
  35. package/dist/commands/chat.js.map +1 -0
  36. package/dist/commands/check-cache.d.ts +3 -0
  37. package/dist/commands/check-cache.d.ts.map +1 -0
  38. package/dist/commands/check-cache.js +267 -0
  39. package/dist/commands/check-cache.js.map +1 -0
  40. package/dist/commands/compare.d.ts +3 -0
  41. package/dist/commands/compare.d.ts.map +1 -0
  42. package/dist/commands/compare.js +131 -0
  43. package/dist/commands/compare.js.map +1 -0
  44. package/dist/commands/config.d.ts +3 -0
  45. package/dist/commands/config.d.ts.map +1 -0
  46. package/dist/commands/config.js +421 -0
  47. package/dist/commands/config.js.map +1 -0
  48. package/dist/commands/craft-workflow.d.ts +3 -0
  49. package/dist/commands/craft-workflow.d.ts.map +1 -0
  50. package/dist/commands/craft-workflow.js +844 -0
  51. package/dist/commands/craft-workflow.js.map +1 -0
  52. package/dist/commands/debug-prompt.d.ts +3 -0
  53. package/dist/commands/debug-prompt.d.ts.map +1 -0
  54. package/dist/commands/debug-prompt.js +614 -0
  55. package/dist/commands/debug-prompt.js.map +1 -0
  56. package/dist/commands/diff-prompts.d.ts +3 -0
  57. package/dist/commands/diff-prompts.d.ts.map +1 -0
  58. package/dist/commands/diff-prompts.js +553 -0
  59. package/dist/commands/diff-prompts.js.map +1 -0
  60. package/dist/commands/high-cost-prompts.d.ts +3 -0
  61. package/dist/commands/high-cost-prompts.d.ts.map +1 -0
  62. package/dist/commands/high-cost-prompts.js +719 -0
  63. package/dist/commands/high-cost-prompts.js.map +1 -0
  64. package/dist/commands/init.d.ts +3 -0
  65. package/dist/commands/init.d.ts.map +1 -0
  66. package/dist/commands/init.js +325 -0
  67. package/dist/commands/init.js.map +1 -0
  68. package/dist/commands/key.d.ts +3 -0
  69. package/dist/commands/key.d.ts.map +1 -0
  70. package/dist/commands/key.js +574 -0
  71. package/dist/commands/key.js.map +1 -0
  72. package/dist/commands/list-models.d.ts +3 -0
  73. package/dist/commands/list-models.d.ts.map +1 -0
  74. package/dist/commands/list-models.js +154 -0
  75. package/dist/commands/list-models.js.map +1 -0
  76. package/dist/commands/models.d.ts +3 -0
  77. package/dist/commands/models.d.ts.map +1 -0
  78. package/dist/commands/models.js +107 -0
  79. package/dist/commands/models.js.map +1 -0
  80. package/dist/commands/optimize.d.ts +3 -0
  81. package/dist/commands/optimize.d.ts.map +1 -0
  82. package/dist/commands/optimize.js +345 -0
  83. package/dist/commands/optimize.js.map +1 -0
  84. package/dist/commands/project.d.ts +3 -0
  85. package/dist/commands/project.d.ts.map +1 -0
  86. package/dist/commands/project.js +475 -0
  87. package/dist/commands/project.js.map +1 -0
  88. package/dist/commands/prompt-metrics.d.ts +3 -0
  89. package/dist/commands/prompt-metrics.d.ts.map +1 -0
  90. package/dist/commands/prompt-metrics.js +665 -0
  91. package/dist/commands/prompt-metrics.js.map +1 -0
  92. package/dist/commands/replay-session.d.ts +3 -0
  93. package/dist/commands/replay-session.d.ts.map +1 -0
  94. package/dist/commands/replay-session.js +615 -0
  95. package/dist/commands/replay-session.js.map +1 -0
  96. package/dist/commands/retry-log.d.ts +3 -0
  97. package/dist/commands/retry-log.d.ts.map +1 -0
  98. package/dist/commands/retry-log.js +686 -0
  99. package/dist/commands/retry-log.js.map +1 -0
  100. package/dist/commands/rewrite-prompt.d.ts +3 -0
  101. package/dist/commands/rewrite-prompt.d.ts.map +1 -0
  102. package/dist/commands/rewrite-prompt.js +802 -0
  103. package/dist/commands/rewrite-prompt.js.map +1 -0
  104. package/dist/commands/set-budget.d.ts +3 -0
  105. package/dist/commands/set-budget.d.ts.map +1 -0
  106. package/dist/commands/set-budget.js +909 -0
  107. package/dist/commands/set-budget.js.map +1 -0
  108. package/dist/commands/simulate-cost.d.ts +3 -0
  109. package/dist/commands/simulate-cost.d.ts.map +1 -0
  110. package/dist/commands/simulate-cost.js +873 -0
  111. package/dist/commands/simulate-cost.js.map +1 -0
  112. package/dist/commands/suggest-models.d.ts +3 -0
  113. package/dist/commands/suggest-models.d.ts.map +1 -0
  114. package/dist/commands/suggest-models.js +674 -0
  115. package/dist/commands/suggest-models.js.map +1 -0
  116. package/dist/commands/test.d.ts +3 -0
  117. package/dist/commands/test.d.ts.map +1 -0
  118. package/dist/commands/test.js +187 -0
  119. package/dist/commands/test.js.map +1 -0
  120. package/dist/commands/trace-workflow.d.ts +3 -0
  121. package/dist/commands/trace-workflow.d.ts.map +1 -0
  122. package/dist/commands/trace-workflow.js +651 -0
  123. package/dist/commands/trace-workflow.js.map +1 -0
  124. package/dist/commands/trace.d.ts +3 -0
  125. package/dist/commands/trace.d.ts.map +1 -0
  126. package/dist/commands/trace.js +468 -0
  127. package/dist/commands/trace.js.map +1 -0
  128. package/dist/commands/track.d.ts +3 -0
  129. package/dist/commands/track.d.ts.map +1 -0
  130. package/dist/commands/track.js +404 -0
  131. package/dist/commands/track.js.map +1 -0
  132. package/dist/index.d.ts +4 -0
  133. package/dist/index.d.ts.map +1 -0
  134. package/dist/index.js +169 -0
  135. package/dist/index.js.map +1 -0
  136. package/dist/utils/config.d.ts +46 -0
  137. package/dist/utils/config.d.ts.map +1 -0
  138. package/dist/utils/config.js +321 -0
  139. package/dist/utils/config.js.map +1 -0
  140. package/dist/utils/logger.d.ts +21 -0
  141. package/dist/utils/logger.d.ts.map +1 -0
  142. package/dist/utils/logger.js +101 -0
  143. package/dist/utils/logger.js.map +1 -0
  144. package/dist/utils/models.d.ts +22 -0
  145. package/dist/utils/models.d.ts.map +1 -0
  146. package/dist/utils/models.js +2251 -0
  147. package/dist/utils/models.js.map +1 -0
  148. package/package.json +107 -0
@@ -0,0 +1,615 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.replaySessionCommand = replaySessionCommand;
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const logger_1 = require("../utils/logger");
42
+ const config_1 = require("../utils/config");
43
+ const axios_1 = __importDefault(require("axios"));
44
+ const readline = __importStar(require("readline"));
45
+ function replaySessionCommand(program) {
46
+ const replayGroup = program
47
+ .command('replay-session')
48
+ .description('🔄 Replay full conversations and step through agent logic');
49
+ // Main replay-session command
50
+ replayGroup
51
+ .option('--format <format>', 'Output format (table, json, csv)', 'table')
52
+ .option('--export <path>', 'Export replay data to file')
53
+ .option('-v, --verbose', 'Show detailed replay information')
54
+ .action(async (options) => {
55
+ try {
56
+ await handleReplaySession(options);
57
+ }
58
+ catch (error) {
59
+ logger_1.logger.error('Replay session command failed:', error);
60
+ process.exit(1);
61
+ }
62
+ });
63
+ // Replay session by ID
64
+ replayGroup
65
+ .command('id <sessionId>')
66
+ .description('🔄 Replay a specific session by ID')
67
+ .option('--mode <mode>', 'Playback mode (cli, webview, step)', 'cli')
68
+ .option('--speed <speed>', 'Playback speed (slow, normal, fast)', 'normal')
69
+ .option('--include-cache', 'Show cache usage vs live calls')
70
+ .option('--include-feedback', 'Show feedback tags per message')
71
+ .option('--include-gallm', 'Show GALLM intervention points')
72
+ .option('--auto-play', 'Auto-play without user interaction')
73
+ .option('--format <format>', 'Output format (table, json, csv)', 'table')
74
+ .option('--export <path>', 'Export replay data to file')
75
+ .option('-v, --verbose', 'Show detailed replay information')
76
+ .action(async (sessionId, options) => {
77
+ try {
78
+ await handleReplaySessionById(sessionId, options);
79
+ }
80
+ catch (error) {
81
+ logger_1.logger.error('Replay session by ID failed:', error);
82
+ process.exit(1);
83
+ }
84
+ });
85
+ // Replay session by workflow
86
+ replayGroup
87
+ .command('workflow <workflowId>')
88
+ .description('🔄 Replay sessions for a specific workflow')
89
+ .option('--mode <mode>', 'Playback mode (cli, webview, step)', 'cli')
90
+ .option('--speed <speed>', 'Playback speed (slow, normal, fast)', 'normal')
91
+ .option('--include-cache', 'Show cache usage vs live calls')
92
+ .option('--include-feedback', 'Show feedback tags per message')
93
+ .option('--include-gallm', 'Show GALLM intervention points')
94
+ .option('--auto-play', 'Auto-play without user interaction')
95
+ .option('--format <format>', 'Output format (table, json, csv)', 'table')
96
+ .option('--export <path>', 'Export replay data to file')
97
+ .option('-v, --verbose', 'Show detailed replay information')
98
+ .action(async (workflowId, options) => {
99
+ try {
100
+ await handleReplaySessionByWorkflow(workflowId, options);
101
+ }
102
+ catch (error) {
103
+ logger_1.logger.error('Replay session by workflow failed:', error);
104
+ process.exit(1);
105
+ }
106
+ });
107
+ // Replay recent sessions
108
+ replayGroup
109
+ .command('recent')
110
+ .description('📋 Show recent sessions for replay')
111
+ .option('-n, --number <count>', 'Number of recent sessions to show', '10')
112
+ .option('--format <format>', 'Output format (table, json, csv)', 'table')
113
+ .option('--export <path>', 'Export session list to file')
114
+ .option('-v, --verbose', 'Show detailed session information')
115
+ .action(async (options) => {
116
+ try {
117
+ await handleReplaySessionRecent(options);
118
+ }
119
+ catch (error) {
120
+ logger_1.logger.error('Replay session recent failed:', error);
121
+ process.exit(1);
122
+ }
123
+ });
124
+ }
125
+ async function handleReplaySession(options) {
126
+ console.log(chalk_1.default.cyan.bold('\n🔄 Session Replay & Conversation Analysis'));
127
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
128
+ console.log(chalk_1.default.yellow('Available commands:'));
129
+ console.log(chalk_1.default.white(' costkatana replay-session id <sessionId> Replay specific session'));
130
+ console.log(chalk_1.default.white(' costkatana replay-session workflow <workflowId> Replay workflow sessions'));
131
+ console.log(chalk_1.default.white(' costkatana replay-session recent Show recent sessions'));
132
+ console.log(chalk_1.default.gray('\nExamples:'));
133
+ console.log(chalk_1.default.white(' costkatana replay-session id session-1234'));
134
+ console.log(chalk_1.default.white(' costkatana replay-session id session-1234 --mode step'));
135
+ console.log(chalk_1.default.white(' costkatana replay-session workflow workflow-98765'));
136
+ console.log(chalk_1.default.white(' costkatana replay-session recent --number 5'));
137
+ console.log(chalk_1.default.gray('\nReplay Features:'));
138
+ console.log(chalk_1.default.white(' • CLI or webview playback modes'));
139
+ console.log(chalk_1.default.white(' • Cache usage vs live call analysis'));
140
+ console.log(chalk_1.default.white(' • Feedback tags per message'));
141
+ console.log(chalk_1.default.white(' • GALLM intervention points'));
142
+ console.log(chalk_1.default.white(' • Step-through agent logic'));
143
+ console.log(chalk_1.default.white(' • Conversation flow visualization'));
144
+ console.log(chalk_1.default.gray('\nPlayback Modes:'));
145
+ console.log(chalk_1.default.white(' • cli - Command line interface playback'));
146
+ console.log(chalk_1.default.white(' • webview - Web-based visual playback'));
147
+ console.log(chalk_1.default.white(' • step - Interactive step-through mode'));
148
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
149
+ }
150
+ async function handleReplaySessionById(sessionId, options) {
151
+ logger_1.logger.info(`🔄 Replaying session: ${sessionId}`);
152
+ try {
153
+ const sessionData = await getSessionById(sessionId, options);
154
+ if (options.mode === 'webview') {
155
+ await replaySessionWebview(sessionData, options);
156
+ }
157
+ else if (options.mode === 'step') {
158
+ await replaySessionStep(sessionData, options);
159
+ }
160
+ else {
161
+ await replaySessionCLI(sessionData, options);
162
+ }
163
+ }
164
+ catch (error) {
165
+ logger_1.logger.error('Failed to replay session:', error);
166
+ process.exit(1);
167
+ }
168
+ }
169
+ async function getSessionById(sessionId, options) {
170
+ const baseUrl = config_1.configManager.get('baseUrl');
171
+ const apiKey = config_1.configManager.get('apiKey');
172
+ if (!baseUrl || !apiKey) {
173
+ console.log(chalk_1.default.red.bold('\n❌ Configuration Missing'));
174
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
175
+ if (!apiKey) {
176
+ console.log(chalk_1.default.yellow('• API Key is not set'));
177
+ }
178
+ if (!baseUrl) {
179
+ console.log(chalk_1.default.yellow('• Base URL is not set'));
180
+ }
181
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
182
+ console.log(chalk_1.default.cyan('To set up your configuration, run:'));
183
+ console.log(chalk_1.default.white(' cost-katana init'));
184
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
185
+ throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
186
+ }
187
+ try {
188
+ const params = new URLSearchParams();
189
+ if (options.includeCache)
190
+ params.append('includeCache', 'true');
191
+ if (options.includeFeedback)
192
+ params.append('includeFeedback', 'true');
193
+ if (options.includeGallm)
194
+ params.append('includeGallm', 'true');
195
+ const response = await axios_1.default.get(`${baseUrl}/api/session/replay/${sessionId}?${params}`, {
196
+ headers: {
197
+ 'Authorization': `Bearer ${apiKey}`,
198
+ 'Content-Type': 'application/json',
199
+ },
200
+ timeout: 30000,
201
+ });
202
+ if (response.status !== 200) {
203
+ throw new Error(`API returned status ${response.status}`);
204
+ }
205
+ if (response.data.success && response.data.data) {
206
+ return response.data.data;
207
+ }
208
+ else {
209
+ throw new Error(response.data.message || 'Invalid response format');
210
+ }
211
+ }
212
+ catch (error) {
213
+ if (error.response) {
214
+ throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
215
+ }
216
+ else if (error.request) {
217
+ throw new Error('No response received from API');
218
+ }
219
+ else {
220
+ throw new Error(`Request failed: ${error.message}`);
221
+ }
222
+ }
223
+ }
224
+ async function replaySessionCLI(session, options) {
225
+ console.log(chalk_1.default.cyan.bold(`\n🔄 Session Replay: ${session.sessionId}`));
226
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
227
+ // Session Information
228
+ console.log(chalk_1.default.yellow.bold('\n📋 Session Information'));
229
+ console.log(chalk_1.default.gray('─'.repeat(50)));
230
+ console.log(chalk_1.default.white('🆔 Session ID:'), chalk_1.default.cyan(session.sessionId));
231
+ console.log(chalk_1.default.white('📅 Created:'), chalk_1.default.cyan(new Date(session.createdAt).toLocaleString()));
232
+ console.log(chalk_1.default.white('⏱️ Duration:'), chalk_1.default.cyan(`${session.duration}ms`));
233
+ console.log(chalk_1.default.white('🤖 Agents:'), chalk_1.default.cyan(session.agents?.join(', ') || 'N/A'));
234
+ console.log(chalk_1.default.white('📊 Status:'), session.status === 'completed' ? chalk_1.default.green(session.status) : chalk_1.default.yellow(session.status));
235
+ // Conversation Flow
236
+ console.log(chalk_1.default.yellow.bold('\n💬 Conversation Flow'));
237
+ console.log(chalk_1.default.gray('─'.repeat(50)));
238
+ if (!session.messages || session.messages.length === 0) {
239
+ console.log(chalk_1.default.yellow('No messages found in this session.'));
240
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
241
+ return;
242
+ }
243
+ const speed = options.speed || 'normal';
244
+ const delay = speed === 'fast' ? 500 : speed === 'slow' ? 2000 : 1000;
245
+ for (let i = 0; i < session.messages.length; i++) {
246
+ const message = session.messages[i];
247
+ console.log(chalk_1.default.white(`\n${i + 1}. ${message.role} (${message.timestamp})`));
248
+ console.log(chalk_1.default.gray(' ─'.repeat(40)));
249
+ // Agent information
250
+ if (message.agent) {
251
+ console.log(chalk_1.default.white(' 🤖 Agent:'), chalk_1.default.cyan(message.agent));
252
+ }
253
+ // Model information
254
+ if (message.model) {
255
+ console.log(chalk_1.default.white(' 🧠 Model:'), chalk_1.default.cyan(message.model));
256
+ }
257
+ // Cache information
258
+ if (options.includeCache && message.cacheInfo) {
259
+ const cacheStatus = message.cacheInfo.hit ? chalk_1.default.green('HIT') : chalk_1.default.red('MISS');
260
+ console.log(chalk_1.default.white(' 💾 Cache:'), cacheStatus);
261
+ if (message.cacheInfo.hit) {
262
+ console.log(chalk_1.default.gray(` Cache Key: ${message.cacheInfo.key}`));
263
+ }
264
+ }
265
+ // GALLM intervention
266
+ if (options.includeGallm && message.gallmIntervention) {
267
+ console.log(chalk_1.default.white(' 🎯 GALLM:'), chalk_1.default.yellow(message.gallmIntervention.type));
268
+ console.log(chalk_1.default.gray(` Reason: ${message.gallmIntervention.reason}`));
269
+ }
270
+ // Message content
271
+ console.log(chalk_1.default.white(' 📝 Content:'));
272
+ const content = message.content.length > 200
273
+ ? message.content.substring(0, 200) + '...'
274
+ : message.content;
275
+ console.log(chalk_1.default.gray(` ${content}`));
276
+ // Feedback
277
+ if (options.includeFeedback && message.feedback) {
278
+ const feedbackColor = message.feedback === 'positive' ? chalk_1.default.green :
279
+ message.feedback === 'negative' ? chalk_1.default.red : chalk_1.default.yellow;
280
+ console.log(chalk_1.default.white(' 🏷️ Feedback:'), feedbackColor(message.feedback));
281
+ }
282
+ // Performance metrics
283
+ if (message.metrics) {
284
+ console.log(chalk_1.default.white(' ⏱️ Latency:'), chalk_1.default.cyan(`${message.metrics.latency}ms`));
285
+ console.log(chalk_1.default.white(' 🔢 Tokens:'), chalk_1.default.cyan(message.metrics.tokens));
286
+ console.log(chalk_1.default.white(' 💰 Cost:'), chalk_1.default.green(`$${message.metrics.cost.toFixed(4)}`));
287
+ }
288
+ // Auto-play delay
289
+ if (!options.autoPlay && i < session.messages.length - 1) {
290
+ await new Promise(resolve => setTimeout(resolve, delay));
291
+ }
292
+ }
293
+ // Session Summary
294
+ console.log(chalk_1.default.yellow.bold('\n📊 Session Summary'));
295
+ console.log(chalk_1.default.gray('─'.repeat(50)));
296
+ console.log(chalk_1.default.white('Total Messages:'), chalk_1.default.cyan(session.messages.length));
297
+ console.log(chalk_1.default.white('Total Cost:'), chalk_1.default.green(`$${session.totalCost.toFixed(4)}`));
298
+ console.log(chalk_1.default.white('Total Tokens:'), chalk_1.default.cyan(session.totalTokens.toLocaleString()));
299
+ console.log(chalk_1.default.white('Average Latency:'), chalk_1.default.cyan(`${session.averageLatency}ms`));
300
+ if (options.includeCache && session.cacheStats) {
301
+ console.log(chalk_1.default.white('Cache Hit Rate:'), chalk_1.default.cyan(`${(session.cacheStats.hitRate * 100).toFixed(1)}%`));
302
+ console.log(chalk_1.default.white('Cache Savings:'), chalk_1.default.green(`$${session.cacheStats.savings.toFixed(4)}`));
303
+ }
304
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
305
+ }
306
+ async function replaySessionStep(session, options) {
307
+ console.log(chalk_1.default.cyan.bold(`\n🔄 Interactive Session Replay: ${session.sessionId}`));
308
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
309
+ if (!session.messages || session.messages.length === 0) {
310
+ console.log(chalk_1.default.yellow('No messages found in this session.'));
311
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
312
+ return;
313
+ }
314
+ const rl = readline.createInterface({
315
+ input: process.stdin,
316
+ output: process.stdout
317
+ });
318
+ let currentStep = 0;
319
+ const totalSteps = session.messages.length;
320
+ console.log(chalk_1.default.yellow(`\n📋 Session has ${totalSteps} messages. Use the following commands:`));
321
+ console.log(chalk_1.default.white(' n/next - Next message'));
322
+ console.log(chalk_1.default.white(' p/prev - Previous message'));
323
+ console.log(chalk_1.default.white(' j/jump <number> - Jump to specific message'));
324
+ console.log(chalk_1.default.white(' s/summary - Show session summary'));
325
+ console.log(chalk_1.default.white(' q/quit - Exit replay'));
326
+ console.log(chalk_1.default.white(' h/help - Show this help'));
327
+ while (currentStep < totalSteps) {
328
+ const message = session.messages[currentStep];
329
+ console.log(chalk_1.default.cyan.bold(`\n[${currentStep + 1}/${totalSteps}] ${message.role} (${message.timestamp})`));
330
+ console.log(chalk_1.default.gray('─'.repeat(50)));
331
+ // Agent information
332
+ if (message.agent) {
333
+ console.log(chalk_1.default.white('🤖 Agent:'), chalk_1.default.cyan(message.agent));
334
+ }
335
+ // Model information
336
+ if (message.model) {
337
+ console.log(chalk_1.default.white('🧠 Model:'), chalk_1.default.cyan(message.model));
338
+ }
339
+ // Cache information
340
+ if (options.includeCache && message.cacheInfo) {
341
+ const cacheStatus = message.cacheInfo.hit ? chalk_1.default.green('HIT') : chalk_1.default.red('MISS');
342
+ console.log(chalk_1.default.white('💾 Cache:'), cacheStatus);
343
+ if (message.cacheInfo.hit) {
344
+ console.log(chalk_1.default.gray(`Cache Key: ${message.cacheInfo.key}`));
345
+ }
346
+ }
347
+ // GALLM intervention
348
+ if (options.includeGallm && message.gallmIntervention) {
349
+ console.log(chalk_1.default.white('🎯 GALLM:'), chalk_1.default.yellow(message.gallmIntervention.type));
350
+ console.log(chalk_1.default.gray(`Reason: ${message.gallmIntervention.reason}`));
351
+ }
352
+ // Message content
353
+ console.log(chalk_1.default.white('📝 Content:'));
354
+ console.log(chalk_1.default.gray(message.content));
355
+ // Feedback
356
+ if (options.includeFeedback && message.feedback) {
357
+ const feedbackColor = message.feedback === 'positive' ? chalk_1.default.green :
358
+ message.feedback === 'negative' ? chalk_1.default.red : chalk_1.default.yellow;
359
+ console.log(chalk_1.default.white('🏷️ Feedback:'), feedbackColor(message.feedback));
360
+ }
361
+ // Performance metrics
362
+ if (message.metrics) {
363
+ console.log(chalk_1.default.white('⏱️ Latency:'), chalk_1.default.cyan(`${message.metrics.latency}ms`));
364
+ console.log(chalk_1.default.white('🔢 Tokens:'), chalk_1.default.cyan(message.metrics.tokens));
365
+ console.log(chalk_1.default.white('💰 Cost:'), chalk_1.default.green(`$${message.metrics.cost.toFixed(4)}`));
366
+ }
367
+ // User input
368
+ const answer = await new Promise((resolve) => {
369
+ rl.question(chalk_1.default.yellow('\nCommand (n/p/j/s/q/h): '), resolve);
370
+ });
371
+ const command = answer.toLowerCase().trim();
372
+ if (command === 'n' || command === 'next') {
373
+ currentStep++;
374
+ }
375
+ else if (command === 'p' || command === 'prev') {
376
+ currentStep = Math.max(0, currentStep - 1);
377
+ }
378
+ else if (command.startsWith('j') || command.startsWith('jump')) {
379
+ const parts = command.split(' ');
380
+ const jumpTo = parseInt(parts[1]) - 1;
381
+ if (jumpTo >= 0 && jumpTo < totalSteps) {
382
+ currentStep = jumpTo;
383
+ }
384
+ else {
385
+ console.log(chalk_1.default.red('Invalid message number.'));
386
+ }
387
+ }
388
+ else if (command === 's' || command === 'summary') {
389
+ displaySessionSummary(session, options);
390
+ }
391
+ else if (command === 'q' || command === 'quit') {
392
+ break;
393
+ }
394
+ else if (command === 'h' || command === 'help') {
395
+ console.log(chalk_1.default.yellow('\nCommands:'));
396
+ console.log(chalk_1.default.white(' n/next - Next message'));
397
+ console.log(chalk_1.default.white(' p/prev - Previous message'));
398
+ console.log(chalk_1.default.white(' j/jump <number> - Jump to specific message'));
399
+ console.log(chalk_1.default.white(' s/summary - Show session summary'));
400
+ console.log(chalk_1.default.white(' q/quit - Exit replay'));
401
+ console.log(chalk_1.default.white(' h/help - Show this help'));
402
+ }
403
+ else {
404
+ console.log(chalk_1.default.red('Invalid command. Type "h" for help.'));
405
+ }
406
+ }
407
+ rl.close();
408
+ console.log(chalk_1.default.gray('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
409
+ }
410
+ async function replaySessionWebview(session, options) {
411
+ console.log(chalk_1.default.cyan.bold(`\n🔄 Webview Session Replay: ${session.sessionId}`));
412
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
413
+ // For webview mode, we would typically open a browser window
414
+ // For now, we'll display a message and fall back to CLI mode
415
+ console.log(chalk_1.default.yellow('🌐 Webview mode is not yet implemented.'));
416
+ console.log(chalk_1.default.white('Falling back to CLI mode...'));
417
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
418
+ await replaySessionCLI(session, options);
419
+ }
420
+ function displaySessionSummary(session, options) {
421
+ console.log(chalk_1.default.yellow.bold('\n📊 Session Summary'));
422
+ console.log(chalk_1.default.gray('─'.repeat(50)));
423
+ console.log(chalk_1.default.white('Session ID:'), chalk_1.default.cyan(session.sessionId));
424
+ console.log(chalk_1.default.white('Created:'), chalk_1.default.cyan(new Date(session.createdAt).toLocaleString()));
425
+ console.log(chalk_1.default.white('Duration:'), chalk_1.default.cyan(`${session.duration}ms`));
426
+ console.log(chalk_1.default.white('Total Messages:'), chalk_1.default.cyan(session.messages.length));
427
+ console.log(chalk_1.default.white('Total Cost:'), chalk_1.default.green(`$${session.totalCost.toFixed(4)}`));
428
+ console.log(chalk_1.default.white('Total Tokens:'), chalk_1.default.cyan(session.totalTokens.toLocaleString()));
429
+ console.log(chalk_1.default.white('Average Latency:'), chalk_1.default.cyan(`${session.averageLatency}ms`));
430
+ if (options.includeCache && session.cacheStats) {
431
+ console.log(chalk_1.default.white('Cache Hit Rate:'), chalk_1.default.cyan(`${(session.cacheStats.hitRate * 100).toFixed(1)}%`));
432
+ console.log(chalk_1.default.white('Cache Savings:'), chalk_1.default.green(`$${session.cacheStats.savings.toFixed(4)}`));
433
+ }
434
+ if (options.includeGallm && session.gallmInterventions) {
435
+ console.log(chalk_1.default.white('GALLM Interventions:'), chalk_1.default.cyan(session.gallmInterventions.length));
436
+ }
437
+ console.log(chalk_1.default.gray('─'.repeat(50)));
438
+ }
439
+ async function handleReplaySessionByWorkflow(workflowId, options) {
440
+ logger_1.logger.info(`🔄 Replaying sessions for workflow: ${workflowId}`);
441
+ try {
442
+ const sessions = await getSessionsByWorkflow(workflowId, options);
443
+ if (sessions.length === 0) {
444
+ console.log(chalk_1.default.yellow('No sessions found for this workflow.'));
445
+ return;
446
+ }
447
+ console.log(chalk_1.default.cyan.bold(`\n🔄 Workflow Sessions: ${workflowId}`));
448
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
449
+ sessions.forEach((session, index) => {
450
+ console.log(chalk_1.default.white(`${index + 1}. ${session.sessionId}`));
451
+ console.log(chalk_1.default.gray(' ─'.repeat(40)));
452
+ console.log(chalk_1.default.white(' 📅 Created:'), chalk_1.default.cyan(new Date(session.createdAt).toLocaleString()));
453
+ console.log(chalk_1.default.white(' ⏱️ Duration:'), chalk_1.default.cyan(`${session.duration}ms`));
454
+ console.log(chalk_1.default.white(' 💰 Cost:'), chalk_1.default.green(`$${session.totalCost.toFixed(4)}`));
455
+ console.log(chalk_1.default.white(' 📊 Status:'), session.status === 'completed' ? chalk_1.default.green(session.status) : chalk_1.default.yellow(session.status));
456
+ });
457
+ console.log(chalk_1.default.gray('\nTo replay a specific session:'));
458
+ console.log(chalk_1.default.white(' costkatana replay-session id <sessionId>'));
459
+ }
460
+ catch (error) {
461
+ logger_1.logger.error('Failed to replay workflow sessions:', error);
462
+ process.exit(1);
463
+ }
464
+ }
465
+ async function getSessionsByWorkflow(workflowId, options) {
466
+ const baseUrl = config_1.configManager.get('baseUrl');
467
+ const apiKey = config_1.configManager.get('apiKey');
468
+ if (!baseUrl || !apiKey) {
469
+ console.log(chalk_1.default.red.bold('\n❌ Configuration Missing'));
470
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
471
+ if (!apiKey) {
472
+ console.log(chalk_1.default.yellow('• API Key is not set'));
473
+ }
474
+ if (!baseUrl) {
475
+ console.log(chalk_1.default.yellow('• Base URL is not set'));
476
+ }
477
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
478
+ console.log(chalk_1.default.cyan('To set up your configuration, run:'));
479
+ console.log(chalk_1.default.white(' cost-katana init'));
480
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
481
+ throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
482
+ }
483
+ try {
484
+ const params = new URLSearchParams();
485
+ params.append('workflowId', workflowId);
486
+ const response = await axios_1.default.get(`${baseUrl}/api/session/replay/workflow?${params}`, {
487
+ headers: {
488
+ 'Authorization': `Bearer ${apiKey}`,
489
+ 'Content-Type': 'application/json',
490
+ },
491
+ timeout: 30000,
492
+ });
493
+ if (response.status !== 200) {
494
+ throw new Error(`API returned status ${response.status}`);
495
+ }
496
+ if (response.data.success && response.data.data) {
497
+ return response.data.data;
498
+ }
499
+ else {
500
+ throw new Error(response.data.message || 'Invalid response format');
501
+ }
502
+ }
503
+ catch (error) {
504
+ if (error.response) {
505
+ throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
506
+ }
507
+ else if (error.request) {
508
+ throw new Error('No response received from API');
509
+ }
510
+ else {
511
+ throw new Error(`Request failed: ${error.message}`);
512
+ }
513
+ }
514
+ }
515
+ async function handleReplaySessionRecent(options) {
516
+ logger_1.logger.info('📋 Fetching recent sessions...');
517
+ try {
518
+ const count = parseInt(options.number) || 10;
519
+ const sessions = await getRecentSessions(count);
520
+ displayRecentSessions(sessions, options);
521
+ }
522
+ catch (error) {
523
+ logger_1.logger.error('Failed to fetch recent sessions:', error);
524
+ process.exit(1);
525
+ }
526
+ }
527
+ async function getRecentSessions(count) {
528
+ const baseUrl = config_1.configManager.get('baseUrl');
529
+ const apiKey = config_1.configManager.get('apiKey');
530
+ if (!baseUrl || !apiKey) {
531
+ console.log(chalk_1.default.red.bold('\n❌ Configuration Missing'));
532
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
533
+ if (!apiKey) {
534
+ console.log(chalk_1.default.yellow('• API Key is not set'));
535
+ }
536
+ if (!baseUrl) {
537
+ console.log(chalk_1.default.yellow('• Base URL is not set'));
538
+ }
539
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
540
+ console.log(chalk_1.default.cyan('To set up your configuration, run:'));
541
+ console.log(chalk_1.default.white(' cost-katana init'));
542
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
543
+ throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
544
+ }
545
+ try {
546
+ const response = await axios_1.default.get(`${baseUrl}/api/session/replay/recent?count=${count}`, {
547
+ headers: {
548
+ 'Authorization': `Bearer ${apiKey}`,
549
+ 'Content-Type': 'application/json',
550
+ },
551
+ timeout: 30000,
552
+ });
553
+ if (response.status !== 200) {
554
+ throw new Error(`API returned status ${response.status}`);
555
+ }
556
+ if (response.data.success && response.data.data) {
557
+ return response.data.data;
558
+ }
559
+ else {
560
+ throw new Error(response.data.message || 'Invalid response format');
561
+ }
562
+ }
563
+ catch (error) {
564
+ if (error.response) {
565
+ throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
566
+ }
567
+ else if (error.request) {
568
+ throw new Error('No response received from API');
569
+ }
570
+ else {
571
+ throw new Error(`Request failed: ${error.message}`);
572
+ }
573
+ }
574
+ }
575
+ function displayRecentSessions(sessions, options) {
576
+ const format = options.format || 'table';
577
+ if (format === 'json') {
578
+ console.log(JSON.stringify(sessions, null, 2));
579
+ return;
580
+ }
581
+ else if (format === 'csv') {
582
+ console.log('Session ID,Workflow ID,Created,Duration,Cost,Status,Messages');
583
+ sessions.forEach(session => {
584
+ console.log(`"${session.sessionId}","${session.workflowId || 'N/A'}","${session.createdAt}","${session.duration}","${session.totalCost}","${session.status}","${session.messageCount}"`);
585
+ });
586
+ return;
587
+ }
588
+ console.log(chalk_1.default.cyan.bold('\n📋 Recent Sessions'));
589
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
590
+ if (sessions.length === 0) {
591
+ console.log(chalk_1.default.yellow('No recent sessions found.'));
592
+ console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
593
+ return;
594
+ }
595
+ sessions.forEach((session, index) => {
596
+ console.log(chalk_1.default.white(`\n${index + 1}. ${session.sessionId}`));
597
+ console.log(chalk_1.default.gray(' ─'.repeat(40)));
598
+ console.log(chalk_1.default.white(' 📅 Created:'), chalk_1.default.cyan(new Date(session.createdAt).toLocaleString()));
599
+ console.log(chalk_1.default.white(' ⏱️ Duration:'), chalk_1.default.cyan(`${session.duration}ms`));
600
+ console.log(chalk_1.default.white(' 💰 Cost:'), chalk_1.default.green(`$${session.totalCost.toFixed(4)}`));
601
+ console.log(chalk_1.default.white(' 📊 Status:'), session.status === 'completed' ? chalk_1.default.green(session.status) : chalk_1.default.yellow(session.status));
602
+ console.log(chalk_1.default.white(' 💬 Messages:'), chalk_1.default.cyan(session.messageCount));
603
+ if (session.workflowId) {
604
+ console.log(chalk_1.default.white(' 🔄 Workflow:'), chalk_1.default.cyan(session.workflowId));
605
+ }
606
+ });
607
+ console.log(chalk_1.default.gray('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
608
+ console.log(chalk_1.default.yellow('💡 Commands:'));
609
+ console.log(chalk_1.default.white(' • Replay session: costkatana replay-session id <sessionId>'));
610
+ console.log(chalk_1.default.white(' • Step mode: costkatana replay-session id <sessionId> --mode step'));
611
+ console.log(chalk_1.default.white(' • With cache info: costkatana replay-session id <sessionId> --include-cache'));
612
+ console.log(chalk_1.default.white(' • With feedback: costkatana replay-session id <sessionId> --include-feedback'));
613
+ console.log(chalk_1.default.white(' • With GALLM: costkatana replay-session id <sessionId> --include-gallm'));
614
+ }
615
+ //# sourceMappingURL=replay-session.js.map