prab-cli 1.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.
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TodoTool = void 0;
4
+ const zod_1 = require("zod");
5
+ const base_1 = require("./base");
6
+ const config_1 = require("../config");
7
+ const ui_1 = require("../ui");
8
+ /**
9
+ * Manage todos for multi-step tasks
10
+ */
11
+ class TodoTool extends base_1.Tool {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.name = 'manage_todos';
15
+ this.description = 'Create, update, or complete todo items to track progress on multi-step tasks. Use this proactively for complex operations.';
16
+ this.requiresConfirmation = false;
17
+ this.destructive = false;
18
+ this.schema = zod_1.z.object({
19
+ action: zod_1.z.enum(['create', 'update', 'complete', 'list', 'clear']).describe('Action to perform'),
20
+ todos: zod_1.z.array(zod_1.z.object({
21
+ id: zod_1.z.string().optional(),
22
+ content: zod_1.z.string(),
23
+ activeForm: zod_1.z.string(),
24
+ status: zod_1.z.enum(['pending', 'in_progress', 'completed'])
25
+ })).optional().describe('Todo items for create/update actions')
26
+ });
27
+ }
28
+ async execute(params) {
29
+ try {
30
+ const session = (0, config_1.getSessionData)();
31
+ let todos = session.todos || [];
32
+ switch (params.action) {
33
+ case 'create': {
34
+ if (!params.todos || params.todos.length === 0) {
35
+ return this.error('No todos provided for create action');
36
+ }
37
+ // Add new todos
38
+ const newTodos = params.todos.map(todo => ({
39
+ id: todo.id || `todo-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
40
+ content: todo.content,
41
+ activeForm: todo.activeForm,
42
+ status: todo.status,
43
+ createdAt: Date.now()
44
+ }));
45
+ todos = [...todos, ...newTodos];
46
+ (0, config_1.setSessionData)({ todos });
47
+ (0, ui_1.showTodoList)(todos);
48
+ return this.success(`Created ${newTodos.length} todo(s)`, { count: newTodos.length, todos });
49
+ }
50
+ case 'update': {
51
+ if (!params.todos || params.todos.length === 0) {
52
+ return this.error('No todos provided for update action');
53
+ }
54
+ // Update existing todos
55
+ for (const update of params.todos) {
56
+ const index = todos.findIndex(t => t.id === update.id || t.content === update.content);
57
+ if (index !== -1) {
58
+ todos[index] = {
59
+ ...todos[index],
60
+ content: update.content,
61
+ activeForm: update.activeForm,
62
+ status: update.status
63
+ };
64
+ }
65
+ }
66
+ (0, config_1.setSessionData)({ todos });
67
+ (0, ui_1.showTodoList)(todos);
68
+ return this.success(`Updated ${params.todos.length} todo(s)`, { todos });
69
+ }
70
+ case 'complete': {
71
+ if (!params.todos || params.todos.length === 0) {
72
+ return this.error('No todos provided for complete action');
73
+ }
74
+ // Mark todos as completed
75
+ for (const completedTodo of params.todos) {
76
+ const index = todos.findIndex(t => t.id === completedTodo.id || t.content === completedTodo.content);
77
+ if (index !== -1) {
78
+ todos[index].status = 'completed';
79
+ }
80
+ }
81
+ (0, config_1.setSessionData)({ todos });
82
+ (0, ui_1.showTodoList)(todos);
83
+ return this.success(`Completed ${params.todos.length} todo(s)`, { todos });
84
+ }
85
+ case 'list': {
86
+ (0, ui_1.showTodoList)(todos);
87
+ const pending = todos.filter(t => t.status === 'pending').length;
88
+ const inProgress = todos.filter(t => t.status === 'in_progress').length;
89
+ const completed = todos.filter(t => t.status === 'completed').length;
90
+ return this.success(`Total todos: ${todos.length} (${pending} pending, ${inProgress} in progress, ${completed} completed)`, { todos, counts: { pending, inProgress, completed } });
91
+ }
92
+ case 'clear': {
93
+ (0, config_1.setSessionData)({ todos: [] });
94
+ return this.success('Cleared all todos');
95
+ }
96
+ default:
97
+ return this.error(`Unknown action: ${params.action}`);
98
+ }
99
+ }
100
+ catch (error) {
101
+ return this.error(`Todo management failed: ${error.message}`);
102
+ }
103
+ }
104
+ }
105
+ exports.TodoTool = TodoTool;
@@ -0,0 +1,314 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.tracker = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const os_1 = __importDefault(require("os"));
10
+ /**
11
+ * Super Logger - Tracks everything happening in the CLI
12
+ */
13
+ class SuperTracker {
14
+ constructor() {
15
+ this.logDir = path_1.default.join(os_1.default.homedir(), '.config', 'groq-cli-tool', 'logs');
16
+ this.sessionId = this.generateSessionId();
17
+ this.logFile = path_1.default.join(this.logDir, `session-${this.sessionId}.jsonl`);
18
+ this.ensureLogDir();
19
+ }
20
+ generateSessionId() {
21
+ const now = new Date();
22
+ return `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}-${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`;
23
+ }
24
+ ensureLogDir() {
25
+ if (!fs_1.default.existsSync(this.logDir)) {
26
+ fs_1.default.mkdirSync(this.logDir, { recursive: true });
27
+ }
28
+ }
29
+ /**
30
+ * Write a log entry to file (with immediate flush)
31
+ */
32
+ write(entry) {
33
+ const line = JSON.stringify(entry) + '\n';
34
+ const fd = fs_1.default.openSync(this.logFile, 'a');
35
+ fs_1.default.writeSync(fd, line);
36
+ fs_1.default.fsyncSync(fd);
37
+ fs_1.default.closeSync(fd);
38
+ }
39
+ /**
40
+ * Log session start
41
+ */
42
+ sessionStart(model, toolCount) {
43
+ this.write({
44
+ timestamp: new Date().toISOString(),
45
+ level: 'info',
46
+ event: 'SESSION_START',
47
+ message: `Session started with model: ${model}`,
48
+ data: { model, toolCount, sessionId: this.sessionId }
49
+ });
50
+ }
51
+ /**
52
+ * Log user prompt received
53
+ */
54
+ promptReceived(prompt) {
55
+ this.write({
56
+ timestamp: new Date().toISOString(),
57
+ level: 'info',
58
+ event: 'PROMPT_RECEIVED',
59
+ message: `User: "${prompt.length > 100 ? prompt.substring(0, 100) + '...' : prompt}"`,
60
+ data: { prompt, length: prompt.length }
61
+ });
62
+ }
63
+ /**
64
+ * Log API request to Groq
65
+ */
66
+ apiRequest(model, messageCount, toolCount) {
67
+ this.write({
68
+ timestamp: new Date().toISOString(),
69
+ level: 'api',
70
+ event: 'API_REQUEST',
71
+ message: `Sending request to Groq API`,
72
+ data: { model, messageCount, toolCount }
73
+ });
74
+ }
75
+ /**
76
+ * Log API response from Groq
77
+ */
78
+ apiResponse(hasContent, hasToolCalls, toolCallCount, duration) {
79
+ this.write({
80
+ timestamp: new Date().toISOString(),
81
+ level: 'api',
82
+ event: 'API_RESPONSE',
83
+ message: `Received response from Groq API`,
84
+ data: { hasContent, hasToolCalls, toolCallCount },
85
+ duration
86
+ });
87
+ }
88
+ /**
89
+ * Log API error
90
+ */
91
+ apiError(error, details) {
92
+ this.write({
93
+ timestamp: new Date().toISOString(),
94
+ level: 'error',
95
+ event: 'API_ERROR',
96
+ message: `API Error: ${error}`,
97
+ data: { error, details }
98
+ });
99
+ }
100
+ /**
101
+ * Log AI response text
102
+ */
103
+ aiResponse(content) {
104
+ this.write({
105
+ timestamp: new Date().toISOString(),
106
+ level: 'ai',
107
+ event: 'AI_RESPONSE',
108
+ message: `AI: "${content.length > 150 ? content.substring(0, 150) + '...' : content}"`,
109
+ data: { content: content.substring(0, 500), length: content.length }
110
+ });
111
+ }
112
+ /**
113
+ * Log AI decided to call tools
114
+ */
115
+ aiToolDecision(toolCalls) {
116
+ const toolNames = toolCalls.map(t => t.name).join(', ');
117
+ this.write({
118
+ timestamp: new Date().toISOString(),
119
+ level: 'ai',
120
+ event: 'AI_TOOL_DECISION',
121
+ message: `AI decided to call: [${toolNames}]`,
122
+ data: { toolCalls }
123
+ });
124
+ }
125
+ /**
126
+ * Log tool execution start
127
+ */
128
+ toolStart(toolName, args) {
129
+ this.write({
130
+ timestamp: new Date().toISOString(),
131
+ level: 'info',
132
+ event: 'TOOL_START',
133
+ message: `Executing tool: ${toolName}`,
134
+ data: { toolName, args }
135
+ });
136
+ }
137
+ /**
138
+ * Log tool execution success
139
+ */
140
+ toolSuccess(toolName, output, duration) {
141
+ this.write({
142
+ timestamp: new Date().toISOString(),
143
+ level: 'success',
144
+ event: 'TOOL_SUCCESS',
145
+ message: `Tool completed: ${toolName}`,
146
+ data: { toolName, outputPreview: output.substring(0, 200), outputLength: output.length },
147
+ duration
148
+ });
149
+ }
150
+ /**
151
+ * Log tool execution failure
152
+ */
153
+ toolError(toolName, error, duration, args) {
154
+ this.write({
155
+ timestamp: new Date().toISOString(),
156
+ level: 'error',
157
+ event: 'TOOL_ERROR',
158
+ message: `Tool failed: ${toolName}`,
159
+ data: { toolName, error, args, errorMessage: error },
160
+ duration
161
+ });
162
+ }
163
+ /**
164
+ * Log tool cancelled by user
165
+ */
166
+ toolCancelled(toolName) {
167
+ this.write({
168
+ timestamp: new Date().toISOString(),
169
+ level: 'warn',
170
+ event: 'TOOL_CANCELLED',
171
+ message: `Tool cancelled by user: ${toolName}`,
172
+ data: { toolName }
173
+ });
174
+ }
175
+ /**
176
+ * Log model initialization
177
+ */
178
+ modelInit(modelId, provider, success, error) {
179
+ this.write({
180
+ timestamp: new Date().toISOString(),
181
+ level: success ? 'success' : 'error',
182
+ event: 'MODEL_INIT',
183
+ message: success ? `Model initialized: ${modelId}` : `Model init failed: ${error}`,
184
+ data: { modelId, provider, success, error }
185
+ });
186
+ }
187
+ /**
188
+ * Log model switch
189
+ */
190
+ modelSwitch(fromModel, toModel, success) {
191
+ this.write({
192
+ timestamp: new Date().toISOString(),
193
+ level: success ? 'success' : 'error',
194
+ event: 'MODEL_SWITCH',
195
+ message: success ? `Switched model: ${fromModel} -> ${toModel}` : `Model switch failed: ${fromModel} -> ${toModel}`,
196
+ data: { fromModel, toModel, success }
197
+ });
198
+ }
199
+ /**
200
+ * Log prompt processing complete
201
+ */
202
+ promptComplete(prompt, duration, iterations) {
203
+ this.write({
204
+ timestamp: new Date().toISOString(),
205
+ level: 'success',
206
+ event: 'PROMPT_COMPLETE',
207
+ message: `Prompt processed successfully`,
208
+ data: { promptPreview: prompt.substring(0, 50), iterations },
209
+ duration
210
+ });
211
+ }
212
+ /**
213
+ * Log prompt processing failed
214
+ */
215
+ promptFailed(prompt, error) {
216
+ this.write({
217
+ timestamp: new Date().toISOString(),
218
+ level: 'error',
219
+ event: 'PROMPT_FAILED',
220
+ message: `Prompt processing failed: ${error}`,
221
+ data: { promptPreview: prompt.substring(0, 50), error }
222
+ });
223
+ }
224
+ /**
225
+ * Log streaming chunk received
226
+ */
227
+ streamChunk(hasContent, hasToolCalls) {
228
+ this.write({
229
+ timestamp: new Date().toISOString(),
230
+ level: 'debug',
231
+ event: 'STREAM_CHUNK',
232
+ message: `Stream chunk: content=${hasContent}, tools=${hasToolCalls}`,
233
+ data: { hasContent, hasToolCalls }
234
+ });
235
+ }
236
+ /**
237
+ * Log iteration in the response loop
238
+ */
239
+ iteration(count, reason) {
240
+ this.write({
241
+ timestamp: new Date().toISOString(),
242
+ level: 'debug',
243
+ event: 'ITERATION',
244
+ message: `Loop iteration ${count}: ${reason}`,
245
+ data: { count, reason }
246
+ });
247
+ }
248
+ /**
249
+ * Log context attachment
250
+ */
251
+ contextAttached(files) {
252
+ this.write({
253
+ timestamp: new Date().toISOString(),
254
+ level: 'info',
255
+ event: 'CONTEXT_ATTACHED',
256
+ message: `Attached ${files.length} file(s) for context`,
257
+ data: { files }
258
+ });
259
+ }
260
+ /**
261
+ * Generic debug log
262
+ */
263
+ debug(message, data) {
264
+ this.write({
265
+ timestamp: new Date().toISOString(),
266
+ level: 'debug',
267
+ event: 'DEBUG',
268
+ message,
269
+ data
270
+ });
271
+ }
272
+ /**
273
+ * Generic warning log
274
+ */
275
+ warn(message, data) {
276
+ this.write({
277
+ timestamp: new Date().toISOString(),
278
+ level: 'warn',
279
+ event: 'WARNING',
280
+ message,
281
+ data
282
+ });
283
+ }
284
+ /**
285
+ * Generic error log
286
+ */
287
+ error(message, error, data) {
288
+ this.write({
289
+ timestamp: new Date().toISOString(),
290
+ level: 'error',
291
+ event: 'ERROR',
292
+ message,
293
+ data: {
294
+ error: error instanceof Error ? error.message : error,
295
+ stack: error instanceof Error ? error.stack : undefined,
296
+ ...data
297
+ }
298
+ });
299
+ }
300
+ /**
301
+ * Get log file path
302
+ */
303
+ getLogFile() {
304
+ return this.logFile;
305
+ }
306
+ /**
307
+ * Get session ID
308
+ */
309
+ getSessionId() {
310
+ return this.sessionId;
311
+ }
312
+ }
313
+ // Singleton instance
314
+ exports.tracker = new SuperTracker();