codebot-ai 1.6.0 → 1.7.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/dist/agent.d.ts +12 -0
- package/dist/agent.js +51 -4
- package/dist/audit.d.ts +31 -9
- package/dist/audit.js +85 -11
- package/dist/cli.js +181 -26
- package/dist/policy.d.ts +123 -0
- package/dist/policy.js +418 -0
- package/dist/sandbox.d.ts +65 -0
- package/dist/sandbox.js +214 -0
- package/dist/telemetry.d.ts +73 -0
- package/dist/telemetry.js +286 -0
- package/dist/tools/execute.js +29 -4
- package/package.json +1 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token & Cost Tracking for CodeBot v1.7.0
|
|
3
|
+
*
|
|
4
|
+
* Tracks per-request and per-session token usage and estimated costs.
|
|
5
|
+
* Supports cost limits and historical usage queries.
|
|
6
|
+
*/
|
|
7
|
+
export interface UsageRecord {
|
|
8
|
+
timestamp: string;
|
|
9
|
+
model: string;
|
|
10
|
+
provider: string;
|
|
11
|
+
inputTokens: number;
|
|
12
|
+
outputTokens: number;
|
|
13
|
+
costUsd: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SessionSummary {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
model: string;
|
|
18
|
+
provider: string;
|
|
19
|
+
startTime: string;
|
|
20
|
+
endTime: string;
|
|
21
|
+
totalInputTokens: number;
|
|
22
|
+
totalOutputTokens: number;
|
|
23
|
+
totalCostUsd: number;
|
|
24
|
+
requestCount: number;
|
|
25
|
+
toolCalls: number;
|
|
26
|
+
filesModified: number;
|
|
27
|
+
}
|
|
28
|
+
export declare class TokenTracker {
|
|
29
|
+
private model;
|
|
30
|
+
private provider;
|
|
31
|
+
private sessionId;
|
|
32
|
+
private records;
|
|
33
|
+
private toolCallCount;
|
|
34
|
+
private filesModifiedSet;
|
|
35
|
+
private startTime;
|
|
36
|
+
private costLimitUsd;
|
|
37
|
+
constructor(model: string, provider: string, sessionId?: string);
|
|
38
|
+
/** Set cost limit in USD. 0 = no limit. */
|
|
39
|
+
setCostLimit(usd: number): void;
|
|
40
|
+
/** Record token usage from an LLM request */
|
|
41
|
+
recordUsage(inputTokens: number, outputTokens: number): UsageRecord;
|
|
42
|
+
/** Record a tool call (for summary) */
|
|
43
|
+
recordToolCall(): void;
|
|
44
|
+
/** Record a file modification (for summary) */
|
|
45
|
+
recordFileModified(filePath: string): void;
|
|
46
|
+
/** Check if cost limit has been exceeded */
|
|
47
|
+
isOverBudget(): boolean;
|
|
48
|
+
/** Get remaining budget in USD (Infinity if no limit) */
|
|
49
|
+
getRemainingBudget(): number;
|
|
50
|
+
getTotalInputTokens(): number;
|
|
51
|
+
getTotalOutputTokens(): number;
|
|
52
|
+
getTotalCost(): number;
|
|
53
|
+
getRequestCount(): number;
|
|
54
|
+
/** Generate a session summary */
|
|
55
|
+
getSummary(): SessionSummary;
|
|
56
|
+
/** Format cost for display */
|
|
57
|
+
formatCost(): string;
|
|
58
|
+
/** Format a compact status line for CLI */
|
|
59
|
+
formatStatusLine(): string;
|
|
60
|
+
/** Save session usage to ~/.codebot/usage/ for historical tracking */
|
|
61
|
+
saveUsage(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Load historical usage from ~/.codebot/usage/
|
|
64
|
+
*/
|
|
65
|
+
static loadHistory(days?: number): SessionSummary[];
|
|
66
|
+
/**
|
|
67
|
+
* Format a historical usage report.
|
|
68
|
+
*/
|
|
69
|
+
static formatUsageReport(days?: number): string;
|
|
70
|
+
private getPricing;
|
|
71
|
+
private isLocalModel;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Token & Cost Tracking for CodeBot v1.7.0
|
|
4
|
+
*
|
|
5
|
+
* Tracks per-request and per-session token usage and estimated costs.
|
|
6
|
+
* Supports cost limits and historical usage queries.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.TokenTracker = void 0;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
const PRICING = {
|
|
47
|
+
// Anthropic
|
|
48
|
+
'claude-opus-4-6': { input: 15.0, output: 75.0 },
|
|
49
|
+
'claude-sonnet-4-20250514': { input: 3.0, output: 15.0 },
|
|
50
|
+
'claude-haiku-3-5': { input: 0.80, output: 4.0 },
|
|
51
|
+
// OpenAI
|
|
52
|
+
'gpt-4o': { input: 2.50, output: 10.0 },
|
|
53
|
+
'gpt-4o-mini': { input: 0.15, output: 0.60 },
|
|
54
|
+
'gpt-4.1': { input: 2.0, output: 8.0 },
|
|
55
|
+
'gpt-4.1-mini': { input: 0.40, output: 1.60 },
|
|
56
|
+
'gpt-4.1-nano': { input: 0.10, output: 0.40 },
|
|
57
|
+
'o1': { input: 15.0, output: 60.0 },
|
|
58
|
+
'o3': { input: 10.0, output: 40.0 },
|
|
59
|
+
'o3-mini': { input: 1.10, output: 4.40 },
|
|
60
|
+
'o4-mini': { input: 1.10, output: 4.40 },
|
|
61
|
+
// Google
|
|
62
|
+
'gemini-2.5-pro': { input: 1.25, output: 10.0 },
|
|
63
|
+
'gemini-2.5-flash': { input: 0.15, output: 0.60 },
|
|
64
|
+
'gemini-2.0-flash': { input: 0.10, output: 0.40 },
|
|
65
|
+
// DeepSeek
|
|
66
|
+
'deepseek-chat': { input: 0.14, output: 0.28 },
|
|
67
|
+
'deepseek-reasoner': { input: 0.55, output: 2.19 },
|
|
68
|
+
// Groq (free tier pricing)
|
|
69
|
+
'llama-3.3-70b-versatile': { input: 0.59, output: 0.79 },
|
|
70
|
+
// Mistral
|
|
71
|
+
'mistral-large-latest': { input: 2.0, output: 6.0 },
|
|
72
|
+
'codestral-latest': { input: 0.30, output: 0.90 },
|
|
73
|
+
// xAI
|
|
74
|
+
'grok-3': { input: 3.0, output: 15.0 },
|
|
75
|
+
'grok-3-mini': { input: 0.30, output: 0.50 },
|
|
76
|
+
};
|
|
77
|
+
// Default pricing for unknown models (conservative estimate)
|
|
78
|
+
const DEFAULT_PRICING = { input: 2.0, output: 8.0 };
|
|
79
|
+
// Free pricing for local models
|
|
80
|
+
const LOCAL_PRICING = { input: 0, output: 0 };
|
|
81
|
+
class TokenTracker {
|
|
82
|
+
model;
|
|
83
|
+
provider;
|
|
84
|
+
sessionId;
|
|
85
|
+
records = [];
|
|
86
|
+
toolCallCount = 0;
|
|
87
|
+
filesModifiedSet = new Set();
|
|
88
|
+
startTime;
|
|
89
|
+
costLimitUsd = 0;
|
|
90
|
+
constructor(model, provider, sessionId) {
|
|
91
|
+
this.model = model;
|
|
92
|
+
this.provider = provider;
|
|
93
|
+
this.sessionId = sessionId || `${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
|
|
94
|
+
this.startTime = new Date().toISOString();
|
|
95
|
+
}
|
|
96
|
+
/** Set cost limit in USD. 0 = no limit. */
|
|
97
|
+
setCostLimit(usd) {
|
|
98
|
+
this.costLimitUsd = usd;
|
|
99
|
+
}
|
|
100
|
+
/** Record token usage from an LLM request */
|
|
101
|
+
recordUsage(inputTokens, outputTokens) {
|
|
102
|
+
const pricing = this.getPricing();
|
|
103
|
+
const costUsd = (inputTokens * pricing.input + outputTokens * pricing.output) / 1_000_000;
|
|
104
|
+
const record = {
|
|
105
|
+
timestamp: new Date().toISOString(),
|
|
106
|
+
model: this.model,
|
|
107
|
+
provider: this.provider,
|
|
108
|
+
inputTokens,
|
|
109
|
+
outputTokens,
|
|
110
|
+
costUsd,
|
|
111
|
+
};
|
|
112
|
+
this.records.push(record);
|
|
113
|
+
return record;
|
|
114
|
+
}
|
|
115
|
+
/** Record a tool call (for summary) */
|
|
116
|
+
recordToolCall() {
|
|
117
|
+
this.toolCallCount++;
|
|
118
|
+
}
|
|
119
|
+
/** Record a file modification (for summary) */
|
|
120
|
+
recordFileModified(filePath) {
|
|
121
|
+
this.filesModifiedSet.add(filePath);
|
|
122
|
+
}
|
|
123
|
+
/** Check if cost limit has been exceeded */
|
|
124
|
+
isOverBudget() {
|
|
125
|
+
if (this.costLimitUsd <= 0)
|
|
126
|
+
return false;
|
|
127
|
+
return this.getTotalCost() >= this.costLimitUsd;
|
|
128
|
+
}
|
|
129
|
+
/** Get remaining budget in USD (Infinity if no limit) */
|
|
130
|
+
getRemainingBudget() {
|
|
131
|
+
if (this.costLimitUsd <= 0)
|
|
132
|
+
return Infinity;
|
|
133
|
+
return Math.max(0, this.costLimitUsd - this.getTotalCost());
|
|
134
|
+
}
|
|
135
|
+
// ── Aggregates ──
|
|
136
|
+
getTotalInputTokens() {
|
|
137
|
+
return this.records.reduce((sum, r) => sum + r.inputTokens, 0);
|
|
138
|
+
}
|
|
139
|
+
getTotalOutputTokens() {
|
|
140
|
+
return this.records.reduce((sum, r) => sum + r.outputTokens, 0);
|
|
141
|
+
}
|
|
142
|
+
getTotalCost() {
|
|
143
|
+
return this.records.reduce((sum, r) => sum + r.costUsd, 0);
|
|
144
|
+
}
|
|
145
|
+
getRequestCount() {
|
|
146
|
+
return this.records.length;
|
|
147
|
+
}
|
|
148
|
+
/** Generate a session summary */
|
|
149
|
+
getSummary() {
|
|
150
|
+
return {
|
|
151
|
+
sessionId: this.sessionId,
|
|
152
|
+
model: this.model,
|
|
153
|
+
provider: this.provider,
|
|
154
|
+
startTime: this.startTime,
|
|
155
|
+
endTime: new Date().toISOString(),
|
|
156
|
+
totalInputTokens: this.getTotalInputTokens(),
|
|
157
|
+
totalOutputTokens: this.getTotalOutputTokens(),
|
|
158
|
+
totalCostUsd: this.getTotalCost(),
|
|
159
|
+
requestCount: this.getRequestCount(),
|
|
160
|
+
toolCalls: this.toolCallCount,
|
|
161
|
+
filesModified: this.filesModifiedSet.size,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/** Format cost for display */
|
|
165
|
+
formatCost() {
|
|
166
|
+
const cost = this.getTotalCost();
|
|
167
|
+
if (cost === 0)
|
|
168
|
+
return 'free (local model)';
|
|
169
|
+
if (cost < 0.01)
|
|
170
|
+
return `< $0.01`;
|
|
171
|
+
return `$${cost.toFixed(4)}`;
|
|
172
|
+
}
|
|
173
|
+
/** Format a compact status line for CLI */
|
|
174
|
+
formatStatusLine() {
|
|
175
|
+
const inTk = this.getTotalInputTokens();
|
|
176
|
+
const outTk = this.getTotalOutputTokens();
|
|
177
|
+
const cost = this.formatCost();
|
|
178
|
+
return `${inTk.toLocaleString()} in / ${outTk.toLocaleString()} out | ${cost}`;
|
|
179
|
+
}
|
|
180
|
+
/** Save session usage to ~/.codebot/usage/ for historical tracking */
|
|
181
|
+
saveUsage() {
|
|
182
|
+
try {
|
|
183
|
+
const usageDir = path.join(os.homedir(), '.codebot', 'usage');
|
|
184
|
+
fs.mkdirSync(usageDir, { recursive: true });
|
|
185
|
+
const summary = this.getSummary();
|
|
186
|
+
const fileName = `usage-${summary.startTime.split('T')[0]}.jsonl`;
|
|
187
|
+
const filePath = path.join(usageDir, fileName);
|
|
188
|
+
fs.appendFileSync(filePath, JSON.stringify(summary) + '\n', 'utf-8');
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
// Usage tracking failures are non-fatal
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Load historical usage from ~/.codebot/usage/
|
|
196
|
+
*/
|
|
197
|
+
static loadHistory(days) {
|
|
198
|
+
const summaries = [];
|
|
199
|
+
try {
|
|
200
|
+
const usageDir = path.join(os.homedir(), '.codebot', 'usage');
|
|
201
|
+
if (!fs.existsSync(usageDir))
|
|
202
|
+
return [];
|
|
203
|
+
const files = fs.readdirSync(usageDir)
|
|
204
|
+
.filter(f => f.startsWith('usage-') && f.endsWith('.jsonl'))
|
|
205
|
+
.sort();
|
|
206
|
+
// Filter by date range if specified
|
|
207
|
+
const cutoff = days
|
|
208
|
+
? new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString()
|
|
209
|
+
: undefined;
|
|
210
|
+
for (const file of files) {
|
|
211
|
+
const content = fs.readFileSync(path.join(usageDir, file), 'utf-8');
|
|
212
|
+
for (const line of content.split('\n')) {
|
|
213
|
+
if (!line.trim())
|
|
214
|
+
continue;
|
|
215
|
+
try {
|
|
216
|
+
const summary = JSON.parse(line);
|
|
217
|
+
if (cutoff && summary.startTime < cutoff)
|
|
218
|
+
continue;
|
|
219
|
+
summaries.push(summary);
|
|
220
|
+
}
|
|
221
|
+
catch { /* skip malformed */ }
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// Can't read usage
|
|
227
|
+
}
|
|
228
|
+
return summaries;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Format a historical usage report.
|
|
232
|
+
*/
|
|
233
|
+
static formatUsageReport(days = 30) {
|
|
234
|
+
const history = TokenTracker.loadHistory(days);
|
|
235
|
+
if (history.length === 0)
|
|
236
|
+
return 'No usage data found.';
|
|
237
|
+
let totalInput = 0;
|
|
238
|
+
let totalOutput = 0;
|
|
239
|
+
let totalCost = 0;
|
|
240
|
+
let totalRequests = 0;
|
|
241
|
+
let totalTools = 0;
|
|
242
|
+
for (const s of history) {
|
|
243
|
+
totalInput += s.totalInputTokens;
|
|
244
|
+
totalOutput += s.totalOutputTokens;
|
|
245
|
+
totalCost += s.totalCostUsd;
|
|
246
|
+
totalRequests += s.requestCount;
|
|
247
|
+
totalTools += s.toolCalls;
|
|
248
|
+
}
|
|
249
|
+
const lines = [
|
|
250
|
+
`Usage Report (last ${days} days)`,
|
|
251
|
+
'─'.repeat(40),
|
|
252
|
+
`Sessions: ${history.length}`,
|
|
253
|
+
`LLM Requests: ${totalRequests.toLocaleString()}`,
|
|
254
|
+
`Tool Calls: ${totalTools.toLocaleString()}`,
|
|
255
|
+
`Input Tokens: ${totalInput.toLocaleString()}`,
|
|
256
|
+
`Output Tokens: ${totalOutput.toLocaleString()}`,
|
|
257
|
+
`Total Cost: $${totalCost.toFixed(4)}`,
|
|
258
|
+
];
|
|
259
|
+
return lines.join('\n');
|
|
260
|
+
}
|
|
261
|
+
// ── Helpers ──
|
|
262
|
+
getPricing() {
|
|
263
|
+
// Local models are free
|
|
264
|
+
if (this.isLocalModel())
|
|
265
|
+
return LOCAL_PRICING;
|
|
266
|
+
// Exact match
|
|
267
|
+
if (PRICING[this.model])
|
|
268
|
+
return PRICING[this.model];
|
|
269
|
+
// Prefix match (for versioned models like claude-sonnet-4-20250514)
|
|
270
|
+
for (const [key, pricing] of Object.entries(PRICING)) {
|
|
271
|
+
if (this.model.startsWith(key))
|
|
272
|
+
return pricing;
|
|
273
|
+
}
|
|
274
|
+
return DEFAULT_PRICING;
|
|
275
|
+
}
|
|
276
|
+
isLocalModel() {
|
|
277
|
+
// Models running on Ollama, LM Studio, vLLM are free
|
|
278
|
+
return !this.provider ||
|
|
279
|
+
this.provider === 'ollama' ||
|
|
280
|
+
this.provider === 'lmstudio' ||
|
|
281
|
+
this.provider === 'vllm' ||
|
|
282
|
+
this.provider === 'local';
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
exports.TokenTracker = TokenTracker;
|
|
286
|
+
//# sourceMappingURL=telemetry.js.map
|
package/dist/tools/execute.js
CHANGED
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ExecuteTool = void 0;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const security_1 = require("../security");
|
|
6
|
+
const sandbox_1 = require("../sandbox");
|
|
7
|
+
const policy_1 = require("../policy");
|
|
6
8
|
const BLOCKED_PATTERNS = [
|
|
7
9
|
// Destructive filesystem operations
|
|
8
10
|
/rm\s+-rf\s+\//,
|
|
@@ -109,25 +111,48 @@ class ExecuteTool {
|
|
|
109
111
|
if (!cwdSafety.safe) {
|
|
110
112
|
return `Error: ${cwdSafety.reason}`;
|
|
111
113
|
}
|
|
112
|
-
|
|
114
|
+
const timeout = args.timeout || 30000;
|
|
115
|
+
// ── v1.7.0: Sandbox routing ──
|
|
116
|
+
const policy = (0, policy_1.loadPolicy)(projectRoot);
|
|
117
|
+
const sandboxMode = policy.execution?.sandbox || 'auto';
|
|
118
|
+
const useSandbox = sandboxMode === 'docker' ||
|
|
119
|
+
(sandboxMode === 'auto' && (0, sandbox_1.isDockerAvailable)());
|
|
120
|
+
if (useSandbox) {
|
|
121
|
+
const result = (0, sandbox_1.sandboxExec)(cmd, projectRoot, {
|
|
122
|
+
network: policy.execution?.network !== false,
|
|
123
|
+
memoryMb: policy.execution?.max_memory_mb || 512,
|
|
124
|
+
timeoutMs: timeout,
|
|
125
|
+
});
|
|
126
|
+
if (result.sandboxed) {
|
|
127
|
+
const output = result.stdout || result.stderr || '(no output)';
|
|
128
|
+
const tag = '[sandboxed]';
|
|
129
|
+
if (result.exitCode !== 0) {
|
|
130
|
+
return `${tag} Exit code ${result.exitCode}\nSTDOUT:\n${result.stdout}\nSTDERR:\n${result.stderr}`;
|
|
131
|
+
}
|
|
132
|
+
return `${tag} ${output}`;
|
|
133
|
+
}
|
|
134
|
+
// Fallthrough: sandboxExec returned sandboxed=false (Docker wasn't available after all)
|
|
135
|
+
}
|
|
136
|
+
// ── Host execution (existing path) ──
|
|
113
137
|
const safeEnv = { ...process.env };
|
|
114
138
|
for (const key of FILTERED_ENV_VARS) {
|
|
115
139
|
delete safeEnv[key];
|
|
116
140
|
}
|
|
141
|
+
const tag = useSandbox ? '[host-fallback]' : '[host]';
|
|
117
142
|
try {
|
|
118
143
|
const output = (0, child_process_1.execSync)(cmd, {
|
|
119
144
|
cwd,
|
|
120
|
-
timeout
|
|
145
|
+
timeout,
|
|
121
146
|
maxBuffer: 1024 * 1024,
|
|
122
147
|
encoding: 'utf-8',
|
|
123
148
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
124
149
|
env: safeEnv,
|
|
125
150
|
});
|
|
126
|
-
return output || '(no output)'
|
|
151
|
+
return `${tag} ${output || '(no output)'}`;
|
|
127
152
|
}
|
|
128
153
|
catch (err) {
|
|
129
154
|
const e = err;
|
|
130
|
-
return
|
|
155
|
+
return `${tag} Exit code ${e.status || 1}\nSTDOUT:\n${e.stdout || ''}\nSTDERR:\n${e.stderr || ''}`;
|
|
131
156
|
}
|
|
132
157
|
}
|
|
133
158
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebot-ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Zero-dependency autonomous AI agent. Code, browse, search, automate. Works with any LLM — Ollama, Claude, GPT, Gemini, DeepSeek, Groq, Mistral, Grok.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|