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.
- package/LICENSE +21 -0
- package/README.md +343 -0
- package/bin/cost-katana.js +20 -0
- package/dist/commands/agent-inspect.d.ts +3 -0
- package/dist/commands/agent-inspect.d.ts.map +1 -0
- package/dist/commands/agent-inspect.js +630 -0
- package/dist/commands/agent-inspect.js.map +1 -0
- package/dist/commands/analytics.d.ts +3 -0
- package/dist/commands/analytics.d.ts.map +1 -0
- package/dist/commands/analytics.js +375 -0
- package/dist/commands/analytics.js.map +1 -0
- package/dist/commands/analyze.d.ts +3 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +286 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/ask.d.ts +3 -0
- package/dist/commands/ask.d.ts.map +1 -0
- package/dist/commands/ask.js +137 -0
- package/dist/commands/ask.js.map +1 -0
- package/dist/commands/audit-firewall.d.ts +3 -0
- package/dist/commands/audit-firewall.d.ts.map +1 -0
- package/dist/commands/audit-firewall.js +737 -0
- package/dist/commands/audit-firewall.js.map +1 -0
- package/dist/commands/budget.d.ts +3 -0
- package/dist/commands/budget.d.ts.map +1 -0
- package/dist/commands/budget.js +283 -0
- package/dist/commands/budget.js.map +1 -0
- package/dist/commands/bulk-optimize.d.ts +3 -0
- package/dist/commands/bulk-optimize.d.ts.map +1 -0
- package/dist/commands/bulk-optimize.js +863 -0
- package/dist/commands/bulk-optimize.js.map +1 -0
- package/dist/commands/chat.d.ts +3 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +292 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/check-cache.d.ts +3 -0
- package/dist/commands/check-cache.d.ts.map +1 -0
- package/dist/commands/check-cache.js +267 -0
- package/dist/commands/check-cache.js.map +1 -0
- package/dist/commands/compare.d.ts +3 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +131 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +421 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/craft-workflow.d.ts +3 -0
- package/dist/commands/craft-workflow.d.ts.map +1 -0
- package/dist/commands/craft-workflow.js +844 -0
- package/dist/commands/craft-workflow.js.map +1 -0
- package/dist/commands/debug-prompt.d.ts +3 -0
- package/dist/commands/debug-prompt.d.ts.map +1 -0
- package/dist/commands/debug-prompt.js +614 -0
- package/dist/commands/debug-prompt.js.map +1 -0
- package/dist/commands/diff-prompts.d.ts +3 -0
- package/dist/commands/diff-prompts.d.ts.map +1 -0
- package/dist/commands/diff-prompts.js +553 -0
- package/dist/commands/diff-prompts.js.map +1 -0
- package/dist/commands/high-cost-prompts.d.ts +3 -0
- package/dist/commands/high-cost-prompts.d.ts.map +1 -0
- package/dist/commands/high-cost-prompts.js +719 -0
- package/dist/commands/high-cost-prompts.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +325 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/key.d.ts +3 -0
- package/dist/commands/key.d.ts.map +1 -0
- package/dist/commands/key.js +574 -0
- package/dist/commands/key.js.map +1 -0
- package/dist/commands/list-models.d.ts +3 -0
- package/dist/commands/list-models.d.ts.map +1 -0
- package/dist/commands/list-models.js +154 -0
- package/dist/commands/list-models.js.map +1 -0
- package/dist/commands/models.d.ts +3 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/models.js +107 -0
- package/dist/commands/models.js.map +1 -0
- package/dist/commands/optimize.d.ts +3 -0
- package/dist/commands/optimize.d.ts.map +1 -0
- package/dist/commands/optimize.js +345 -0
- package/dist/commands/optimize.js.map +1 -0
- package/dist/commands/project.d.ts +3 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +475 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/prompt-metrics.d.ts +3 -0
- package/dist/commands/prompt-metrics.d.ts.map +1 -0
- package/dist/commands/prompt-metrics.js +665 -0
- package/dist/commands/prompt-metrics.js.map +1 -0
- package/dist/commands/replay-session.d.ts +3 -0
- package/dist/commands/replay-session.d.ts.map +1 -0
- package/dist/commands/replay-session.js +615 -0
- package/dist/commands/replay-session.js.map +1 -0
- package/dist/commands/retry-log.d.ts +3 -0
- package/dist/commands/retry-log.d.ts.map +1 -0
- package/dist/commands/retry-log.js +686 -0
- package/dist/commands/retry-log.js.map +1 -0
- package/dist/commands/rewrite-prompt.d.ts +3 -0
- package/dist/commands/rewrite-prompt.d.ts.map +1 -0
- package/dist/commands/rewrite-prompt.js +802 -0
- package/dist/commands/rewrite-prompt.js.map +1 -0
- package/dist/commands/set-budget.d.ts +3 -0
- package/dist/commands/set-budget.d.ts.map +1 -0
- package/dist/commands/set-budget.js +909 -0
- package/dist/commands/set-budget.js.map +1 -0
- package/dist/commands/simulate-cost.d.ts +3 -0
- package/dist/commands/simulate-cost.d.ts.map +1 -0
- package/dist/commands/simulate-cost.js +873 -0
- package/dist/commands/simulate-cost.js.map +1 -0
- package/dist/commands/suggest-models.d.ts +3 -0
- package/dist/commands/suggest-models.d.ts.map +1 -0
- package/dist/commands/suggest-models.js +674 -0
- package/dist/commands/suggest-models.js.map +1 -0
- package/dist/commands/test.d.ts +3 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +187 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/trace-workflow.d.ts +3 -0
- package/dist/commands/trace-workflow.d.ts.map +1 -0
- package/dist/commands/trace-workflow.js +651 -0
- package/dist/commands/trace-workflow.js.map +1 -0
- package/dist/commands/trace.d.ts +3 -0
- package/dist/commands/trace.d.ts.map +1 -0
- package/dist/commands/trace.js +468 -0
- package/dist/commands/trace.js.map +1 -0
- package/dist/commands/track.d.ts +3 -0
- package/dist/commands/track.d.ts.map +1 -0
- package/dist/commands/track.js +404 -0
- package/dist/commands/track.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +169 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config.d.ts +46 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +321 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +101 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/models.d.ts +22 -0
- package/dist/utils/models.d.ts.map +1 -0
- package/dist/utils/models.js +2251 -0
- package/dist/utils/models.js.map +1 -0
- 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
|