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,863 @@
|
|
|
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.bulkOptimizeCommand = bulkOptimizeCommand;
|
|
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 fs = __importStar(require("fs"));
|
|
45
|
+
const csv_parser_1 = __importDefault(require("csv-parser"));
|
|
46
|
+
const csv_writer_1 = require("csv-writer");
|
|
47
|
+
function bulkOptimizeCommand(program) {
|
|
48
|
+
const bulkGroup = program
|
|
49
|
+
.command('bulk-optimize')
|
|
50
|
+
.description('š Analyze and optimize multiple high-frequency prompts in one go');
|
|
51
|
+
// Main bulk-optimize command
|
|
52
|
+
bulkGroup
|
|
53
|
+
.option('--file <path>', 'CSV file with prompts to optimize')
|
|
54
|
+
.option('--format <format>', 'Output format (table, json, csv)', 'table')
|
|
55
|
+
.option('--export <path>', 'Export optimization results to file')
|
|
56
|
+
.option('-v, --verbose', 'Show detailed optimization analysis')
|
|
57
|
+
.option('--include-token-analysis', 'Include detailed token analysis')
|
|
58
|
+
.option('--include-cost-breakdown', 'Include detailed cost breakdown')
|
|
59
|
+
.option('--include-optimization-suggestions', 'Include optimization suggestions')
|
|
60
|
+
.option('--include-priority-ranking', 'Include priority ranking')
|
|
61
|
+
.action(async (options) => {
|
|
62
|
+
try {
|
|
63
|
+
await handleBulkOptimize(options);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger_1.logger.error('Bulk optimize command failed:', error);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
// Batch optimization with different strategies
|
|
71
|
+
bulkGroup
|
|
72
|
+
.command('strategies')
|
|
73
|
+
.description('š Optimize prompts using different strategies')
|
|
74
|
+
.option('--file <path>', 'CSV file with prompts to optimize')
|
|
75
|
+
.option('--strategies <strategies>', 'Comma-separated optimization strategies')
|
|
76
|
+
.option('--format <format>', 'Output format (table, json, csv)', 'table')
|
|
77
|
+
.option('--export <path>', 'Export strategy results to file')
|
|
78
|
+
.option('-v, --verbose', 'Show detailed strategy analysis')
|
|
79
|
+
.option('--include-token-analysis', 'Include detailed token analysis')
|
|
80
|
+
.option('--include-cost-breakdown', 'Include detailed cost breakdown')
|
|
81
|
+
.option('--include-comparison', 'Include strategy comparison')
|
|
82
|
+
.action(async (options) => {
|
|
83
|
+
try {
|
|
84
|
+
await handleStrategyOptimization(options);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
logger_1.logger.error('Strategy optimization failed:', error);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
// Priority-based optimization
|
|
92
|
+
bulkGroup
|
|
93
|
+
.command('priority')
|
|
94
|
+
.description('š Optimize prompts based on priority and impact')
|
|
95
|
+
.option('--file <path>', 'CSV file with prompts to optimize')
|
|
96
|
+
.option('--priority-criteria <criteria>', 'Priority criteria (cost, frequency, impact)', 'cost')
|
|
97
|
+
.option('--format <format>', 'Output format (table, json, csv)', 'table')
|
|
98
|
+
.option('--export <path>', 'Export priority results to file')
|
|
99
|
+
.option('-v, --verbose', 'Show detailed priority analysis')
|
|
100
|
+
.option('--include-token-analysis', 'Include detailed token analysis')
|
|
101
|
+
.option('--include-cost-breakdown', 'Include detailed cost breakdown')
|
|
102
|
+
.option('--include-impact-analysis', 'Include impact analysis')
|
|
103
|
+
.action(async (options) => {
|
|
104
|
+
try {
|
|
105
|
+
await handlePriorityOptimization(options);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
logger_1.logger.error('Priority optimization failed:', error);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
// Model-specific optimization
|
|
113
|
+
bulkGroup
|
|
114
|
+
.command('models')
|
|
115
|
+
.description('š Optimize prompts for specific models')
|
|
116
|
+
.option('--file <path>', 'CSV file with prompts to optimize')
|
|
117
|
+
.option('--target-models <models>', 'Comma-separated target models')
|
|
118
|
+
.option('--format <format>', 'Output format (table, json, csv)', 'table')
|
|
119
|
+
.option('--export <path>', 'Export model results to file')
|
|
120
|
+
.option('-v, --verbose', 'Show detailed model analysis')
|
|
121
|
+
.option('--include-token-analysis', 'Include detailed token analysis')
|
|
122
|
+
.option('--include-cost-breakdown', 'Include detailed cost breakdown')
|
|
123
|
+
.option('--include-model-comparison', 'Include model comparison')
|
|
124
|
+
.action(async (options) => {
|
|
125
|
+
try {
|
|
126
|
+
await handleModelOptimization(options);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
logger_1.logger.error('Model optimization failed:', error);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
// Frequency-based optimization
|
|
134
|
+
bulkGroup
|
|
135
|
+
.command('frequency')
|
|
136
|
+
.description('š Optimize prompts based on usage frequency')
|
|
137
|
+
.option('--file <path>', 'CSV file with prompts to optimize')
|
|
138
|
+
.option('--frequency-threshold <threshold>', 'Minimum frequency threshold', '100')
|
|
139
|
+
.option('--format <format>', 'Output format (table, json, csv)', 'table')
|
|
140
|
+
.option('--export <path>', 'Export frequency results to file')
|
|
141
|
+
.option('-v, --verbose', 'Show detailed frequency analysis')
|
|
142
|
+
.option('--include-token-analysis', 'Include detailed token analysis')
|
|
143
|
+
.option('--include-cost-breakdown', 'Include detailed cost breakdown')
|
|
144
|
+
.option('--include-frequency-analysis', 'Include frequency analysis')
|
|
145
|
+
.action(async (options) => {
|
|
146
|
+
try {
|
|
147
|
+
await handleFrequencyOptimization(options);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
logger_1.logger.error('Frequency optimization failed:', error);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
// Cost-based optimization
|
|
155
|
+
bulkGroup
|
|
156
|
+
.command('cost')
|
|
157
|
+
.description('š Optimize prompts based on cost impact')
|
|
158
|
+
.option('--file <path>', 'CSV file with prompts to optimize')
|
|
159
|
+
.option('--cost-threshold <threshold>', 'Minimum cost threshold', '0.01')
|
|
160
|
+
.option('--format <format>', 'Output format (table, json, csv)', 'table')
|
|
161
|
+
.option('--export <path>', 'Export cost results to file')
|
|
162
|
+
.option('-v, --verbose', 'Show detailed cost analysis')
|
|
163
|
+
.option('--include-token-analysis', 'Include detailed token analysis')
|
|
164
|
+
.option('--include-cost-breakdown', 'Include detailed cost breakdown')
|
|
165
|
+
.option('--include-cost-analysis', 'Include cost analysis')
|
|
166
|
+
.action(async (options) => {
|
|
167
|
+
try {
|
|
168
|
+
await handleCostOptimization(options);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
logger_1.logger.error('Cost optimization failed:', error);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
async function handleBulkOptimize(options) {
|
|
177
|
+
logger_1.logger.info('š Running bulk optimization...');
|
|
178
|
+
try {
|
|
179
|
+
const prompts = await loadPromptsFromFile(options.file);
|
|
180
|
+
const optimization = await runBulkOptimization(prompts, options);
|
|
181
|
+
displayBulkOptimizationResults(optimization, options);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
logger_1.logger.error('Failed to run bulk optimization:', error);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function loadPromptsFromFile(filePath) {
|
|
189
|
+
return new Promise((resolve, reject) => {
|
|
190
|
+
const prompts = [];
|
|
191
|
+
fs.createReadStream(filePath)
|
|
192
|
+
.pipe((0, csv_parser_1.default)())
|
|
193
|
+
.on('data', (row) => {
|
|
194
|
+
prompts.push({
|
|
195
|
+
promptId: row.prompt_id,
|
|
196
|
+
promptText: row.prompt_text,
|
|
197
|
+
model: row.model,
|
|
198
|
+
frequency: parseInt(row.frequency) || 1,
|
|
199
|
+
currentCost: parseFloat(row.current_cost) || 0
|
|
200
|
+
});
|
|
201
|
+
})
|
|
202
|
+
.on('end', () => {
|
|
203
|
+
resolve(prompts);
|
|
204
|
+
})
|
|
205
|
+
.on('error', (error) => {
|
|
206
|
+
reject(new Error(`Failed to read CSV file: ${error.message}`));
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
async function runBulkOptimization(prompts, options) {
|
|
211
|
+
const baseUrl = config_1.configManager.get('baseUrl');
|
|
212
|
+
const apiKey = config_1.configManager.get('apiKey');
|
|
213
|
+
if (!baseUrl || !apiKey) {
|
|
214
|
+
console.log(chalk_1.default.red.bold('\nā Configuration Missing'));
|
|
215
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
216
|
+
if (!apiKey) {
|
|
217
|
+
console.log(chalk_1.default.yellow('⢠API Key is not set'));
|
|
218
|
+
}
|
|
219
|
+
if (!baseUrl) {
|
|
220
|
+
console.log(chalk_1.default.yellow('⢠Base URL is not set'));
|
|
221
|
+
}
|
|
222
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
223
|
+
console.log(chalk_1.default.cyan('To set up your configuration, run:'));
|
|
224
|
+
console.log(chalk_1.default.white(' cost-katana init'));
|
|
225
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n'));
|
|
226
|
+
throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const params = new URLSearchParams();
|
|
230
|
+
if (options.includeTokenAnalysis)
|
|
231
|
+
params.append('includeTokenAnalysis', 'true');
|
|
232
|
+
if (options.includeCostBreakdown)
|
|
233
|
+
params.append('includeCostBreakdown', 'true');
|
|
234
|
+
if (options.includeOptimizationSuggestions)
|
|
235
|
+
params.append('includeOptimizationSuggestions', 'true');
|
|
236
|
+
if (options.includePriorityRanking)
|
|
237
|
+
params.append('includePriorityRanking', 'true');
|
|
238
|
+
const response = await axios_1.default.post(`${baseUrl}/api/bulk-optimize?${params}`, {
|
|
239
|
+
prompts: prompts,
|
|
240
|
+
options: {
|
|
241
|
+
includeTokenAnalysis: options.includeTokenAnalysis,
|
|
242
|
+
includeCostBreakdown: options.includeCostBreakdown,
|
|
243
|
+
includeOptimizationSuggestions: options.includeOptimizationSuggestions,
|
|
244
|
+
includePriorityRanking: options.includePriorityRanking
|
|
245
|
+
}
|
|
246
|
+
}, {
|
|
247
|
+
headers: {
|
|
248
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
249
|
+
'Content-Type': 'application/json',
|
|
250
|
+
},
|
|
251
|
+
timeout: 60000,
|
|
252
|
+
});
|
|
253
|
+
if (response.status !== 200) {
|
|
254
|
+
throw new Error(`API returned status ${response.status}`);
|
|
255
|
+
}
|
|
256
|
+
if (response.data.success && response.data.data) {
|
|
257
|
+
return response.data.data;
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
throw new Error(response.data.message || 'Invalid response format');
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
if (error.response) {
|
|
265
|
+
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
|
|
266
|
+
}
|
|
267
|
+
else if (error.request) {
|
|
268
|
+
throw new Error('No response received from API');
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
throw new Error(`Request failed: ${error.message}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function displayBulkOptimizationResults(optimization, options) {
|
|
276
|
+
const format = options.format || 'table';
|
|
277
|
+
if (format === 'json') {
|
|
278
|
+
console.log(JSON.stringify(optimization, null, 2));
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
else if (format === 'csv') {
|
|
282
|
+
console.log('Prompt ID,Original Tokens,Optimized Tokens,Token Reduction,Original Cost,Optimized Cost,Cost Savings,Priority');
|
|
283
|
+
optimization.results.forEach((result) => {
|
|
284
|
+
console.log(`"${result.promptId}","${result.originalTokens}","${result.optimizedTokens}","${result.tokenReduction}","${result.originalCost}","${result.optimizedCost}","${result.costSavings}","${result.priority}"`);
|
|
285
|
+
});
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
console.log(chalk_1.default.cyan.bold('\nš Bulk Optimization Results'));
|
|
289
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
290
|
+
// Summary Statistics
|
|
291
|
+
console.log(chalk_1.default.yellow.bold('\nš Summary Statistics'));
|
|
292
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
293
|
+
console.log(chalk_1.default.white('Total Prompts:'), chalk_1.default.cyan(optimization.totalPrompts));
|
|
294
|
+
console.log(chalk_1.default.white('Total Token Reduction:'), chalk_1.default.green(`${optimization.totalTokenReduction.toLocaleString()} tokens`));
|
|
295
|
+
console.log(chalk_1.default.white('Total Cost Savings:'), chalk_1.default.green(`$${optimization.totalCostSavings.toFixed(4)}`));
|
|
296
|
+
console.log(chalk_1.default.white('Average Token Reduction:'), chalk_1.default.cyan(`${optimization.averageTokenReduction}%`));
|
|
297
|
+
console.log(chalk_1.default.white('Average Cost Savings:'), chalk_1.default.cyan(`${optimization.averageCostSavings}%`));
|
|
298
|
+
console.log(chalk_1.default.white('High Impact Prompts:'), chalk_1.default.yellow(optimization.highImpactPrompts));
|
|
299
|
+
// Individual Results
|
|
300
|
+
console.log(chalk_1.default.yellow.bold('\nš Individual Results'));
|
|
301
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
302
|
+
optimization.results.forEach((result, index) => {
|
|
303
|
+
const priorityColor = result.priority === 'high' ? chalk_1.default.red :
|
|
304
|
+
result.priority === 'medium' ? chalk_1.default.yellow : chalk_1.default.green;
|
|
305
|
+
const savingsColor = result.costSavings > 0 ? chalk_1.default.green : chalk_1.default.red;
|
|
306
|
+
console.log(chalk_1.default.white(`\n${index + 1}. ${result.promptId}:`));
|
|
307
|
+
console.log(chalk_1.default.gray(' ā'.repeat(40)));
|
|
308
|
+
// Basic Info
|
|
309
|
+
console.log(chalk_1.default.white(' Model:'), chalk_1.default.cyan(result.model));
|
|
310
|
+
console.log(chalk_1.default.white(' Priority:'), priorityColor(result.priority));
|
|
311
|
+
console.log(chalk_1.default.white(' Frequency:'), chalk_1.default.cyan(result.frequency));
|
|
312
|
+
// Token Analysis
|
|
313
|
+
console.log(chalk_1.default.white(' Original Tokens:'), chalk_1.default.cyan(result.originalTokens.toLocaleString()));
|
|
314
|
+
console.log(chalk_1.default.white(' Optimized Tokens:'), chalk_1.default.cyan(result.optimizedTokens.toLocaleString()));
|
|
315
|
+
console.log(chalk_1.default.white(' Token Reduction:'), chalk_1.default.green(`${result.tokenReduction}%`));
|
|
316
|
+
// Cost Analysis
|
|
317
|
+
console.log(chalk_1.default.white(' Original Cost:'), chalk_1.default.cyan(`$${result.originalCost.toFixed(4)}`));
|
|
318
|
+
console.log(chalk_1.default.white(' Optimized Cost:'), chalk_1.default.cyan(`$${result.optimizedCost.toFixed(4)}`));
|
|
319
|
+
console.log(chalk_1.default.white(' Cost Savings:'), savingsColor(`$${result.costSavings.toFixed(4)}`));
|
|
320
|
+
// Impact Analysis
|
|
321
|
+
if (result.impact) {
|
|
322
|
+
console.log(chalk_1.default.white(' Impact Score:'), chalk_1.default.cyan(result.impact.score));
|
|
323
|
+
console.log(chalk_1.default.white(' Impact Notes:'), chalk_1.default.gray(result.impact.notes));
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
// Token Analysis
|
|
327
|
+
if (optimization.tokenAnalysis) {
|
|
328
|
+
console.log(chalk_1.default.yellow.bold('\nš¢ Token Analysis'));
|
|
329
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
330
|
+
console.log(chalk_1.default.white('Total Token Reduction:'), chalk_1.default.green(`${optimization.tokenAnalysis.totalReduction.toLocaleString()} tokens`));
|
|
331
|
+
console.log(chalk_1.default.white('Average Token Reduction:'), chalk_1.default.cyan(`${optimization.tokenAnalysis.averageReduction}%`));
|
|
332
|
+
console.log(chalk_1.default.white('Max Token Reduction:'), chalk_1.default.green(`${optimization.tokenAnalysis.maxReduction}%`));
|
|
333
|
+
console.log(chalk_1.default.white('Min Token Reduction:'), chalk_1.default.cyan(`${optimization.tokenAnalysis.minReduction}%`));
|
|
334
|
+
if (optimization.tokenAnalysis.breakdown) {
|
|
335
|
+
console.log(chalk_1.default.white('\nToken Reduction Breakdown:'));
|
|
336
|
+
Object.entries(optimization.tokenAnalysis.breakdown).forEach(([range, count]) => {
|
|
337
|
+
console.log(chalk_1.default.gray(` ${range}: ${count} prompts`));
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Cost Breakdown
|
|
342
|
+
if (optimization.costBreakdown) {
|
|
343
|
+
console.log(chalk_1.default.yellow.bold('\nš° Cost Breakdown'));
|
|
344
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
345
|
+
console.log(chalk_1.default.white('Total Cost Savings:'), chalk_1.default.green(`$${optimization.costBreakdown.totalSavings.toFixed(4)}`));
|
|
346
|
+
console.log(chalk_1.default.white('Average Cost Savings:'), chalk_1.default.cyan(`${optimization.costBreakdown.averageSavings}%`));
|
|
347
|
+
console.log(chalk_1.default.white('Max Cost Savings:'), chalk_1.default.green(`$${optimization.costBreakdown.maxSavings.toFixed(4)}`));
|
|
348
|
+
console.log(chalk_1.default.white('ROI Impact:'), chalk_1.default.cyan(`${optimization.costBreakdown.roiImpact}%`));
|
|
349
|
+
if (optimization.costBreakdown.byModel) {
|
|
350
|
+
console.log(chalk_1.default.white('\nSavings by Model:'));
|
|
351
|
+
Object.entries(optimization.costBreakdown.byModel).forEach(([model, data]) => {
|
|
352
|
+
console.log(chalk_1.default.gray(` ${model}: $${data.savings.toFixed(4)} (${data.percentage}%)`));
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// Priority Ranking
|
|
357
|
+
if (optimization.priorityRanking) {
|
|
358
|
+
console.log(chalk_1.default.yellow.bold('\nš Priority Ranking'));
|
|
359
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
360
|
+
optimization.priorityRanking.forEach((prompt, index) => {
|
|
361
|
+
const rankColor = index < 3 ? chalk_1.default.green : index < 6 ? chalk_1.default.yellow : chalk_1.default.gray;
|
|
362
|
+
console.log(chalk_1.default.white(`${index + 1}. ${prompt.promptId}:`));
|
|
363
|
+
console.log(chalk_1.default.gray(` Priority: ${rankColor(prompt.priority)}`));
|
|
364
|
+
console.log(chalk_1.default.gray(` Impact Score: ${prompt.impactScore}`));
|
|
365
|
+
console.log(chalk_1.default.gray(` Potential Savings: $${prompt.potentialSavings.toFixed(4)}`));
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
// Optimization Suggestions
|
|
369
|
+
if (optimization.suggestions && optimization.suggestions.length > 0) {
|
|
370
|
+
console.log(chalk_1.default.yellow.bold('\nš” Optimization Suggestions'));
|
|
371
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
372
|
+
optimization.suggestions.forEach((suggestion, index) => {
|
|
373
|
+
console.log(chalk_1.default.white(`\n${index + 1}. ${suggestion.type}:`));
|
|
374
|
+
console.log(chalk_1.default.gray(` ${suggestion.description}`));
|
|
375
|
+
console.log(chalk_1.default.gray(` Potential Savings: $${suggestion.potentialSavings.toFixed(4)}`));
|
|
376
|
+
console.log(chalk_1.default.gray(` Implementation: ${suggestion.implementation}`));
|
|
377
|
+
console.log(chalk_1.default.gray(` Priority: ${suggestion.priority}`));
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
// Export Results
|
|
381
|
+
if (options.export) {
|
|
382
|
+
try {
|
|
383
|
+
exportResults(optimization, options.export, format);
|
|
384
|
+
console.log(chalk_1.default.green(`\nā
Results exported to: ${options.export}`));
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
console.log(chalk_1.default.red(`\nā Failed to export results: ${error}`));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
391
|
+
}
|
|
392
|
+
async function exportResults(optimization, filePath, format) {
|
|
393
|
+
if (format === 'json') {
|
|
394
|
+
fs.writeFileSync(filePath, JSON.stringify(optimization, null, 2));
|
|
395
|
+
}
|
|
396
|
+
else if (format === 'csv') {
|
|
397
|
+
const csvWriter = (0, csv_writer_1.createObjectCsvWriter)({
|
|
398
|
+
path: filePath,
|
|
399
|
+
header: [
|
|
400
|
+
{ id: 'promptId', title: 'Prompt ID' },
|
|
401
|
+
{ id: 'model', title: 'Model' },
|
|
402
|
+
{ id: 'originalTokens', title: 'Original Tokens' },
|
|
403
|
+
{ id: 'optimizedTokens', title: 'Optimized Tokens' },
|
|
404
|
+
{ id: 'tokenReduction', title: 'Token Reduction %' },
|
|
405
|
+
{ id: 'originalCost', title: 'Original Cost' },
|
|
406
|
+
{ id: 'optimizedCost', title: 'Optimized Cost' },
|
|
407
|
+
{ id: 'costSavings', title: 'Cost Savings' },
|
|
408
|
+
{ id: 'priority', title: 'Priority' },
|
|
409
|
+
{ id: 'frequency', title: 'Frequency' }
|
|
410
|
+
]
|
|
411
|
+
});
|
|
412
|
+
await csvWriter.writeRecords(optimization.results);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
async function handleStrategyOptimization(options) {
|
|
416
|
+
logger_1.logger.info('š Running strategy-based optimization...');
|
|
417
|
+
try {
|
|
418
|
+
const prompts = await loadPromptsFromFile(options.file);
|
|
419
|
+
const strategies = options.strategies ? options.strategies.split(',') : ['token-reduction', 'cost-optimization', 'quality-preservation'];
|
|
420
|
+
const optimization = await runStrategyOptimization(prompts, strategies, options);
|
|
421
|
+
displayStrategyOptimizationResults(optimization, options);
|
|
422
|
+
}
|
|
423
|
+
catch (error) {
|
|
424
|
+
logger_1.logger.error('Failed to run strategy optimization:', error);
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
async function runStrategyOptimization(prompts, strategies, options) {
|
|
429
|
+
const baseUrl = config_1.configManager.get('baseUrl');
|
|
430
|
+
const apiKey = config_1.configManager.get('apiKey');
|
|
431
|
+
if (!baseUrl || !apiKey) {
|
|
432
|
+
throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
|
|
433
|
+
}
|
|
434
|
+
try {
|
|
435
|
+
const params = new URLSearchParams();
|
|
436
|
+
params.append('strategies', strategies.join(','));
|
|
437
|
+
if (options.includeTokenAnalysis)
|
|
438
|
+
params.append('includeTokenAnalysis', 'true');
|
|
439
|
+
if (options.includeCostBreakdown)
|
|
440
|
+
params.append('includeCostBreakdown', 'true');
|
|
441
|
+
if (options.includeComparison)
|
|
442
|
+
params.append('includeComparison', 'true');
|
|
443
|
+
const response = await axios_1.default.post(`${baseUrl}/api/bulk-optimize/strategies?${params}`, {
|
|
444
|
+
prompts: prompts,
|
|
445
|
+
strategies: strategies,
|
|
446
|
+
options: {
|
|
447
|
+
includeTokenAnalysis: options.includeTokenAnalysis,
|
|
448
|
+
includeCostBreakdown: options.includeCostBreakdown,
|
|
449
|
+
includeComparison: options.includeComparison
|
|
450
|
+
}
|
|
451
|
+
}, {
|
|
452
|
+
headers: {
|
|
453
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
454
|
+
'Content-Type': 'application/json',
|
|
455
|
+
},
|
|
456
|
+
timeout: 60000,
|
|
457
|
+
});
|
|
458
|
+
if (response.status !== 200) {
|
|
459
|
+
throw new Error(`API returned status ${response.status}`);
|
|
460
|
+
}
|
|
461
|
+
if (response.data.success && response.data.data) {
|
|
462
|
+
return response.data.data;
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
throw new Error(response.data.message || 'Invalid response format');
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (error) {
|
|
469
|
+
if (error.response) {
|
|
470
|
+
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
|
|
471
|
+
}
|
|
472
|
+
else if (error.request) {
|
|
473
|
+
throw new Error('No response received from API');
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
throw new Error(`Request failed: ${error.message}`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
function displayStrategyOptimizationResults(optimization, options) {
|
|
481
|
+
const format = options.format || 'table';
|
|
482
|
+
if (format === 'json') {
|
|
483
|
+
console.log(JSON.stringify(optimization, null, 2));
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
console.log(chalk_1.default.cyan.bold('\nš Strategy Optimization Results'));
|
|
487
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
488
|
+
// Strategy Comparison
|
|
489
|
+
console.log(chalk_1.default.yellow.bold('\nš Strategy Comparison'));
|
|
490
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
491
|
+
optimization.strategyResults.forEach((strategy) => {
|
|
492
|
+
console.log(chalk_1.default.white(`\n${strategy.name}:`));
|
|
493
|
+
console.log(chalk_1.default.gray(' ā'.repeat(40)));
|
|
494
|
+
console.log(chalk_1.default.white(' Total Savings:'), chalk_1.default.green(`$${strategy.totalSavings.toFixed(4)}`));
|
|
495
|
+
console.log(chalk_1.default.white(' Token Reduction:'), chalk_1.default.cyan(`${strategy.tokenReduction}%`));
|
|
496
|
+
console.log(chalk_1.default.white(' Cost Reduction:'), chalk_1.default.green(`${strategy.costReduction}%`));
|
|
497
|
+
console.log(chalk_1.default.white(' Quality Impact:'), chalk_1.default.cyan(`${strategy.qualityImpact}%`));
|
|
498
|
+
console.log(chalk_1.default.white(' Prompts Optimized:'), chalk_1.default.cyan(strategy.promptsOptimized));
|
|
499
|
+
});
|
|
500
|
+
// Best Strategy
|
|
501
|
+
console.log(chalk_1.default.yellow.bold('\nš Best Strategy'));
|
|
502
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
503
|
+
console.log(chalk_1.default.white('Strategy:'), chalk_1.default.cyan(optimization.bestStrategy.name));
|
|
504
|
+
console.log(chalk_1.default.white('Total Savings:'), chalk_1.default.green(`$${optimization.bestStrategy.savings.toFixed(4)}`));
|
|
505
|
+
console.log(chalk_1.default.white('Efficiency Score:'), chalk_1.default.cyan(`${optimization.bestStrategy.efficiencyScore}%`));
|
|
506
|
+
console.log(chalk_1.default.white('Implementation:'), chalk_1.default.gray(optimization.bestStrategy.implementation));
|
|
507
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
508
|
+
}
|
|
509
|
+
async function handlePriorityOptimization(options) {
|
|
510
|
+
logger_1.logger.info('š Running priority-based optimization...');
|
|
511
|
+
try {
|
|
512
|
+
const prompts = await loadPromptsFromFile(options.file);
|
|
513
|
+
const optimization = await runPriorityOptimization(prompts, options);
|
|
514
|
+
displayPriorityOptimizationResults(optimization, options);
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
logger_1.logger.error('Failed to run priority optimization:', error);
|
|
518
|
+
process.exit(1);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
async function runPriorityOptimization(prompts, options) {
|
|
522
|
+
const baseUrl = config_1.configManager.get('baseUrl');
|
|
523
|
+
const apiKey = config_1.configManager.get('apiKey');
|
|
524
|
+
if (!baseUrl || !apiKey) {
|
|
525
|
+
throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
|
|
526
|
+
}
|
|
527
|
+
try {
|
|
528
|
+
const params = new URLSearchParams();
|
|
529
|
+
params.append('priorityCriteria', options.priorityCriteria || 'cost');
|
|
530
|
+
if (options.includeTokenAnalysis)
|
|
531
|
+
params.append('includeTokenAnalysis', 'true');
|
|
532
|
+
if (options.includeCostBreakdown)
|
|
533
|
+
params.append('includeCostBreakdown', 'true');
|
|
534
|
+
if (options.includeImpactAnalysis)
|
|
535
|
+
params.append('includeImpactAnalysis', 'true');
|
|
536
|
+
const response = await axios_1.default.post(`${baseUrl}/api/bulk-optimize/priority?${params}`, {
|
|
537
|
+
prompts: prompts,
|
|
538
|
+
priorityCriteria: options.priorityCriteria || 'cost',
|
|
539
|
+
options: {
|
|
540
|
+
includeTokenAnalysis: options.includeTokenAnalysis,
|
|
541
|
+
includeCostBreakdown: options.includeCostBreakdown,
|
|
542
|
+
includeImpactAnalysis: options.includeImpactAnalysis
|
|
543
|
+
}
|
|
544
|
+
}, {
|
|
545
|
+
headers: {
|
|
546
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
547
|
+
'Content-Type': 'application/json',
|
|
548
|
+
},
|
|
549
|
+
timeout: 60000,
|
|
550
|
+
});
|
|
551
|
+
if (response.status !== 200) {
|
|
552
|
+
throw new Error(`API returned status ${response.status}`);
|
|
553
|
+
}
|
|
554
|
+
if (response.data.success && response.data.data) {
|
|
555
|
+
return response.data.data;
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
throw new Error(response.data.message || 'Invalid response format');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
catch (error) {
|
|
562
|
+
if (error.response) {
|
|
563
|
+
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
|
|
564
|
+
}
|
|
565
|
+
else if (error.request) {
|
|
566
|
+
throw new Error('No response received from API');
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
throw new Error(`Request failed: ${error.message}`);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
function displayPriorityOptimizationResults(optimization, options) {
|
|
574
|
+
const format = options.format || 'table';
|
|
575
|
+
if (format === 'json') {
|
|
576
|
+
console.log(JSON.stringify(optimization, null, 2));
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
console.log(chalk_1.default.cyan.bold('\nš Priority Optimization Results'));
|
|
580
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
581
|
+
// Priority Breakdown
|
|
582
|
+
console.log(chalk_1.default.yellow.bold('\nš Priority Breakdown'));
|
|
583
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
584
|
+
console.log(chalk_1.default.white('High Priority:'), chalk_1.default.red(`${optimization.priorityBreakdown.high} prompts`));
|
|
585
|
+
console.log(chalk_1.default.white('Medium Priority:'), chalk_1.default.yellow(`${optimization.priorityBreakdown.medium} prompts`));
|
|
586
|
+
console.log(chalk_1.default.white('Low Priority:'), chalk_1.default.green(`${optimization.priorityBreakdown.low} prompts`));
|
|
587
|
+
// Impact Analysis
|
|
588
|
+
if (optimization.impactAnalysis) {
|
|
589
|
+
console.log(chalk_1.default.yellow.bold('\nšÆ Impact Analysis'));
|
|
590
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
591
|
+
console.log(chalk_1.default.white('High Impact Savings:'), chalk_1.default.green(`$${optimization.impactAnalysis.highImpactSavings.toFixed(4)}`));
|
|
592
|
+
console.log(chalk_1.default.white('Medium Impact Savings:'), chalk_1.default.yellow(`$${optimization.impactAnalysis.mediumImpactSavings.toFixed(4)}`));
|
|
593
|
+
console.log(chalk_1.default.white('Low Impact Savings:'), chalk_1.default.cyan(`$${optimization.impactAnalysis.lowImpactSavings.toFixed(4)}`));
|
|
594
|
+
}
|
|
595
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
596
|
+
}
|
|
597
|
+
async function handleModelOptimization(options) {
|
|
598
|
+
logger_1.logger.info('š Running model-specific optimization...');
|
|
599
|
+
try {
|
|
600
|
+
const prompts = await loadPromptsFromFile(options.file);
|
|
601
|
+
const targetModels = options.targetModels ? options.targetModels.split(',') : ['gpt-4', 'gpt-3.5-turbo', 'claude-3-sonnet'];
|
|
602
|
+
const optimization = await runModelOptimization(prompts, targetModels, options);
|
|
603
|
+
displayModelOptimizationResults(optimization, options);
|
|
604
|
+
}
|
|
605
|
+
catch (error) {
|
|
606
|
+
logger_1.logger.error('Failed to run model optimization:', error);
|
|
607
|
+
process.exit(1);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
async function runModelOptimization(prompts, targetModels, options) {
|
|
611
|
+
const baseUrl = config_1.configManager.get('baseUrl');
|
|
612
|
+
const apiKey = config_1.configManager.get('apiKey');
|
|
613
|
+
if (!baseUrl || !apiKey) {
|
|
614
|
+
throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
|
|
615
|
+
}
|
|
616
|
+
try {
|
|
617
|
+
const params = new URLSearchParams();
|
|
618
|
+
params.append('targetModels', targetModels.join(','));
|
|
619
|
+
if (options.includeTokenAnalysis)
|
|
620
|
+
params.append('includeTokenAnalysis', 'true');
|
|
621
|
+
if (options.includeCostBreakdown)
|
|
622
|
+
params.append('includeCostBreakdown', 'true');
|
|
623
|
+
if (options.includeModelComparison)
|
|
624
|
+
params.append('includeModelComparison', 'true');
|
|
625
|
+
const response = await axios_1.default.post(`${baseUrl}/api/bulk-optimize/models?${params}`, {
|
|
626
|
+
prompts: prompts,
|
|
627
|
+
targetModels: targetModels,
|
|
628
|
+
options: {
|
|
629
|
+
includeTokenAnalysis: options.includeTokenAnalysis,
|
|
630
|
+
includeCostBreakdown: options.includeCostBreakdown,
|
|
631
|
+
includeModelComparison: options.includeModelComparison
|
|
632
|
+
}
|
|
633
|
+
}, {
|
|
634
|
+
headers: {
|
|
635
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
636
|
+
'Content-Type': 'application/json',
|
|
637
|
+
},
|
|
638
|
+
timeout: 60000,
|
|
639
|
+
});
|
|
640
|
+
if (response.status !== 200) {
|
|
641
|
+
throw new Error(`API returned status ${response.status}`);
|
|
642
|
+
}
|
|
643
|
+
if (response.data.success && response.data.data) {
|
|
644
|
+
return response.data.data;
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
throw new Error(response.data.message || 'Invalid response format');
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
catch (error) {
|
|
651
|
+
if (error.response) {
|
|
652
|
+
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
|
|
653
|
+
}
|
|
654
|
+
else if (error.request) {
|
|
655
|
+
throw new Error('No response received from API');
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
throw new Error(`Request failed: ${error.message}`);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function displayModelOptimizationResults(optimization, options) {
|
|
663
|
+
const format = options.format || 'table';
|
|
664
|
+
if (format === 'json') {
|
|
665
|
+
console.log(JSON.stringify(optimization, null, 2));
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
console.log(chalk_1.default.cyan.bold('\nš Model Optimization Results'));
|
|
669
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
670
|
+
// Model Comparison
|
|
671
|
+
console.log(chalk_1.default.yellow.bold('\nš Model Comparison'));
|
|
672
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
673
|
+
optimization.modelResults.forEach((model) => {
|
|
674
|
+
console.log(chalk_1.default.white(`\n${model.name}:`));
|
|
675
|
+
console.log(chalk_1.default.gray(' ā'.repeat(40)));
|
|
676
|
+
console.log(chalk_1.default.white(' Total Savings:'), chalk_1.default.green(`$${model.totalSavings.toFixed(4)}`));
|
|
677
|
+
console.log(chalk_1.default.white(' Token Reduction:'), chalk_1.default.cyan(`${model.tokenReduction}%`));
|
|
678
|
+
console.log(chalk_1.default.white(' Cost Reduction:'), chalk_1.default.green(`${model.costReduction}%`));
|
|
679
|
+
console.log(chalk_1.default.white(' Prompts Optimized:'), chalk_1.default.cyan(model.promptsOptimized));
|
|
680
|
+
});
|
|
681
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
682
|
+
}
|
|
683
|
+
async function handleFrequencyOptimization(options) {
|
|
684
|
+
logger_1.logger.info('š Running frequency-based optimization...');
|
|
685
|
+
try {
|
|
686
|
+
const prompts = await loadPromptsFromFile(options.file);
|
|
687
|
+
const threshold = parseInt(options.frequencyThreshold) || 100;
|
|
688
|
+
const optimization = await runFrequencyOptimization(prompts, threshold, options);
|
|
689
|
+
displayFrequencyOptimizationResults(optimization, options);
|
|
690
|
+
}
|
|
691
|
+
catch (error) {
|
|
692
|
+
logger_1.logger.error('Failed to run frequency optimization:', error);
|
|
693
|
+
process.exit(1);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
async function runFrequencyOptimization(prompts, threshold, options) {
|
|
697
|
+
const baseUrl = config_1.configManager.get('baseUrl');
|
|
698
|
+
const apiKey = config_1.configManager.get('apiKey');
|
|
699
|
+
if (!baseUrl || !apiKey) {
|
|
700
|
+
throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
const params = new URLSearchParams();
|
|
704
|
+
params.append('threshold', threshold.toString());
|
|
705
|
+
if (options.includeTokenAnalysis)
|
|
706
|
+
params.append('includeTokenAnalysis', 'true');
|
|
707
|
+
if (options.includeCostBreakdown)
|
|
708
|
+
params.append('includeCostBreakdown', 'true');
|
|
709
|
+
if (options.includeFrequencyAnalysis)
|
|
710
|
+
params.append('includeFrequencyAnalysis', 'true');
|
|
711
|
+
const response = await axios_1.default.post(`${baseUrl}/api/bulk-optimize/frequency?${params}`, {
|
|
712
|
+
prompts: prompts,
|
|
713
|
+
threshold: threshold,
|
|
714
|
+
options: {
|
|
715
|
+
includeTokenAnalysis: options.includeTokenAnalysis,
|
|
716
|
+
includeCostBreakdown: options.includeCostBreakdown,
|
|
717
|
+
includeFrequencyAnalysis: options.includeFrequencyAnalysis
|
|
718
|
+
}
|
|
719
|
+
}, {
|
|
720
|
+
headers: {
|
|
721
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
722
|
+
'Content-Type': 'application/json',
|
|
723
|
+
},
|
|
724
|
+
timeout: 60000,
|
|
725
|
+
});
|
|
726
|
+
if (response.status !== 200) {
|
|
727
|
+
throw new Error(`API returned status ${response.status}`);
|
|
728
|
+
}
|
|
729
|
+
if (response.data.success && response.data.data) {
|
|
730
|
+
return response.data.data;
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
throw new Error(response.data.message || 'Invalid response format');
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
catch (error) {
|
|
737
|
+
if (error.response) {
|
|
738
|
+
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
|
|
739
|
+
}
|
|
740
|
+
else if (error.request) {
|
|
741
|
+
throw new Error('No response received from API');
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
throw new Error(`Request failed: ${error.message}`);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
function displayFrequencyOptimizationResults(optimization, options) {
|
|
749
|
+
const format = options.format || 'table';
|
|
750
|
+
if (format === 'json') {
|
|
751
|
+
console.log(JSON.stringify(optimization, null, 2));
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
console.log(chalk_1.default.cyan.bold('\nš Frequency Optimization Results'));
|
|
755
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
756
|
+
// Frequency Analysis
|
|
757
|
+
console.log(chalk_1.default.yellow.bold('\nš Frequency Analysis'));
|
|
758
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
759
|
+
console.log(chalk_1.default.white('Threshold:'), chalk_1.default.cyan(optimization.threshold));
|
|
760
|
+
console.log(chalk_1.default.white('High Frequency Prompts:'), chalk_1.default.red(optimization.highFrequencyPrompts));
|
|
761
|
+
console.log(chalk_1.default.white('Medium Frequency Prompts:'), chalk_1.default.yellow(optimization.mediumFrequencyPrompts));
|
|
762
|
+
console.log(chalk_1.default.white('Low Frequency Prompts:'), chalk_1.default.green(optimization.lowFrequencyPrompts));
|
|
763
|
+
// Frequency Impact
|
|
764
|
+
if (optimization.frequencyImpact) {
|
|
765
|
+
console.log(chalk_1.default.yellow.bold('\nšÆ Frequency Impact'));
|
|
766
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
767
|
+
console.log(chalk_1.default.white('High Frequency Savings:'), chalk_1.default.green(`$${optimization.frequencyImpact.highFrequencySavings.toFixed(4)}`));
|
|
768
|
+
console.log(chalk_1.default.white('Medium Frequency Savings:'), chalk_1.default.yellow(`$${optimization.frequencyImpact.mediumFrequencySavings.toFixed(4)}`));
|
|
769
|
+
console.log(chalk_1.default.white('Low Frequency Savings:'), chalk_1.default.cyan(`$${optimization.frequencyImpact.lowFrequencySavings.toFixed(4)}`));
|
|
770
|
+
}
|
|
771
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
772
|
+
}
|
|
773
|
+
async function handleCostOptimization(options) {
|
|
774
|
+
logger_1.logger.info('š Running cost-based optimization...');
|
|
775
|
+
try {
|
|
776
|
+
const prompts = await loadPromptsFromFile(options.file);
|
|
777
|
+
const threshold = parseFloat(options.costThreshold) || 0.01;
|
|
778
|
+
const optimization = await runCostOptimization(prompts, threshold, options);
|
|
779
|
+
displayCostOptimizationResults(optimization, options);
|
|
780
|
+
}
|
|
781
|
+
catch (error) {
|
|
782
|
+
logger_1.logger.error('Failed to run cost optimization:', error);
|
|
783
|
+
process.exit(1);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
async function runCostOptimization(prompts, threshold, options) {
|
|
787
|
+
const baseUrl = config_1.configManager.get('baseUrl');
|
|
788
|
+
const apiKey = config_1.configManager.get('apiKey');
|
|
789
|
+
if (!baseUrl || !apiKey) {
|
|
790
|
+
throw new Error('Configuration incomplete. Please run "cost-katana init" to set up your API key and base URL.');
|
|
791
|
+
}
|
|
792
|
+
try {
|
|
793
|
+
const params = new URLSearchParams();
|
|
794
|
+
params.append('threshold', threshold.toString());
|
|
795
|
+
if (options.includeTokenAnalysis)
|
|
796
|
+
params.append('includeTokenAnalysis', 'true');
|
|
797
|
+
if (options.includeCostBreakdown)
|
|
798
|
+
params.append('includeCostBreakdown', 'true');
|
|
799
|
+
if (options.includeCostAnalysis)
|
|
800
|
+
params.append('includeCostAnalysis', 'true');
|
|
801
|
+
const response = await axios_1.default.post(`${baseUrl}/api/bulk-optimize/cost?${params}`, {
|
|
802
|
+
prompts: prompts,
|
|
803
|
+
threshold: threshold,
|
|
804
|
+
options: {
|
|
805
|
+
includeTokenAnalysis: options.includeTokenAnalysis,
|
|
806
|
+
includeCostBreakdown: options.includeCostBreakdown,
|
|
807
|
+
includeCostAnalysis: options.includeCostAnalysis
|
|
808
|
+
}
|
|
809
|
+
}, {
|
|
810
|
+
headers: {
|
|
811
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
812
|
+
'Content-Type': 'application/json',
|
|
813
|
+
},
|
|
814
|
+
timeout: 60000,
|
|
815
|
+
});
|
|
816
|
+
if (response.status !== 200) {
|
|
817
|
+
throw new Error(`API returned status ${response.status}`);
|
|
818
|
+
}
|
|
819
|
+
if (response.data.success && response.data.data) {
|
|
820
|
+
return response.data.data;
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
throw new Error(response.data.message || 'Invalid response format');
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
catch (error) {
|
|
827
|
+
if (error.response) {
|
|
828
|
+
throw new Error(`API Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`);
|
|
829
|
+
}
|
|
830
|
+
else if (error.request) {
|
|
831
|
+
throw new Error('No response received from API');
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
throw new Error(`Request failed: ${error.message}`);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
function displayCostOptimizationResults(optimization, options) {
|
|
839
|
+
const format = options.format || 'table';
|
|
840
|
+
if (format === 'json') {
|
|
841
|
+
console.log(JSON.stringify(optimization, null, 2));
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
console.log(chalk_1.default.cyan.bold('\nš Cost Optimization Results'));
|
|
845
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
846
|
+
// Cost Analysis
|
|
847
|
+
console.log(chalk_1.default.yellow.bold('\nš Cost Analysis'));
|
|
848
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
849
|
+
console.log(chalk_1.default.white('Threshold:'), chalk_1.default.cyan(`$${optimization.threshold}`));
|
|
850
|
+
console.log(chalk_1.default.white('High Cost Prompts:'), chalk_1.default.red(optimization.highCostPrompts));
|
|
851
|
+
console.log(chalk_1.default.white('Medium Cost Prompts:'), chalk_1.default.yellow(optimization.mediumCostPrompts));
|
|
852
|
+
console.log(chalk_1.default.white('Low Cost Prompts:'), chalk_1.default.green(optimization.lowCostPrompts));
|
|
853
|
+
// Cost Impact
|
|
854
|
+
if (optimization.costImpact) {
|
|
855
|
+
console.log(chalk_1.default.yellow.bold('\nšÆ Cost Impact'));
|
|
856
|
+
console.log(chalk_1.default.gray('ā'.repeat(50)));
|
|
857
|
+
console.log(chalk_1.default.white('High Cost Savings:'), chalk_1.default.green(`$${optimization.costImpact.highCostSavings.toFixed(4)}`));
|
|
858
|
+
console.log(chalk_1.default.white('Medium Cost Savings:'), chalk_1.default.yellow(`$${optimization.costImpact.mediumCostSavings.toFixed(4)}`));
|
|
859
|
+
console.log(chalk_1.default.white('Low Cost Savings:'), chalk_1.default.cyan(`$${optimization.costImpact.lowCostSavings.toFixed(4)}`));
|
|
860
|
+
}
|
|
861
|
+
console.log(chalk_1.default.gray('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
862
|
+
}
|
|
863
|
+
//# sourceMappingURL=bulk-optimize.js.map
|