copilot-liku-cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/ARCHITECTURE.md +411 -0
  2. package/CONFIGURATION.md +302 -0
  3. package/CONTRIBUTING.md +225 -0
  4. package/ELECTRON_README.md +121 -0
  5. package/INSTALLATION.md +350 -0
  6. package/LICENSE.md +1 -0
  7. package/PROJECT_STATUS.md +229 -0
  8. package/QUICKSTART.md +255 -0
  9. package/README.md +167 -0
  10. package/TESTING.md +274 -0
  11. package/package.json +61 -0
  12. package/scripts/start.js +30 -0
  13. package/src/assets/tray-icon.png +0 -0
  14. package/src/cli/commands/agent.js +327 -0
  15. package/src/cli/commands/click.js +108 -0
  16. package/src/cli/commands/drag.js +85 -0
  17. package/src/cli/commands/find.js +109 -0
  18. package/src/cli/commands/keys.js +132 -0
  19. package/src/cli/commands/mouse.js +79 -0
  20. package/src/cli/commands/repl.js +290 -0
  21. package/src/cli/commands/screenshot.js +72 -0
  22. package/src/cli/commands/scroll.js +74 -0
  23. package/src/cli/commands/start.js +67 -0
  24. package/src/cli/commands/type.js +57 -0
  25. package/src/cli/commands/wait.js +84 -0
  26. package/src/cli/commands/window.js +104 -0
  27. package/src/cli/liku.js +249 -0
  28. package/src/cli/util/output.js +174 -0
  29. package/src/main/agents/base-agent.js +410 -0
  30. package/src/main/agents/builder.js +484 -0
  31. package/src/main/agents/index.js +62 -0
  32. package/src/main/agents/orchestrator.js +362 -0
  33. package/src/main/agents/researcher.js +511 -0
  34. package/src/main/agents/state-manager.js +344 -0
  35. package/src/main/agents/supervisor.js +365 -0
  36. package/src/main/agents/verifier.js +452 -0
  37. package/src/main/ai-service.js +1633 -0
  38. package/src/main/index.js +2208 -0
  39. package/src/main/inspect-service.js +467 -0
  40. package/src/main/system-automation.js +1186 -0
  41. package/src/main/ui-automation/config.js +76 -0
  42. package/src/main/ui-automation/core/helpers.js +41 -0
  43. package/src/main/ui-automation/core/index.js +15 -0
  44. package/src/main/ui-automation/core/powershell.js +82 -0
  45. package/src/main/ui-automation/elements/finder.js +274 -0
  46. package/src/main/ui-automation/elements/index.js +14 -0
  47. package/src/main/ui-automation/elements/wait.js +66 -0
  48. package/src/main/ui-automation/index.js +164 -0
  49. package/src/main/ui-automation/interactions/element-click.js +211 -0
  50. package/src/main/ui-automation/interactions/high-level.js +230 -0
  51. package/src/main/ui-automation/interactions/index.js +47 -0
  52. package/src/main/ui-automation/keyboard/index.js +15 -0
  53. package/src/main/ui-automation/keyboard/input.js +179 -0
  54. package/src/main/ui-automation/mouse/click.js +186 -0
  55. package/src/main/ui-automation/mouse/drag.js +88 -0
  56. package/src/main/ui-automation/mouse/index.js +30 -0
  57. package/src/main/ui-automation/mouse/movement.js +51 -0
  58. package/src/main/ui-automation/mouse/scroll.js +116 -0
  59. package/src/main/ui-automation/screenshot.js +183 -0
  60. package/src/main/ui-automation/window/index.js +23 -0
  61. package/src/main/ui-automation/window/manager.js +305 -0
  62. package/src/main/utils/time.js +62 -0
  63. package/src/main/visual-awareness.js +597 -0
  64. package/src/renderer/chat/chat.js +671 -0
  65. package/src/renderer/chat/index.html +725 -0
  66. package/src/renderer/chat/preload.js +112 -0
  67. package/src/renderer/overlay/index.html +648 -0
  68. package/src/renderer/overlay/overlay.js +782 -0
  69. package/src/renderer/overlay/preload.js +90 -0
  70. package/src/shared/grid-math.js +82 -0
  71. package/src/shared/inspect-types.js +230 -0
@@ -0,0 +1,410 @@
1
+ /**
2
+ * Base Agent Class
3
+ *
4
+ * Foundation for all agent types in the multi-agent system.
5
+ * Provides common functionality for AI interaction, tool usage, and handoffs.
6
+ */
7
+
8
+ const EventEmitter = require('events');
9
+
10
+ // Agent roles enum
11
+ const AgentRole = {
12
+ SUPERVISOR: 'supervisor',
13
+ BUILDER: 'builder',
14
+ VERIFIER: 'verifier',
15
+ RESEARCHER: 'researcher'
16
+ };
17
+
18
+ // Agent capabilities
19
+ const AgentCapabilities = {
20
+ // Core capabilities
21
+ SEARCH: 'search',
22
+ READ: 'read',
23
+ EDIT: 'edit',
24
+ EXECUTE: 'execute',
25
+
26
+ // Advanced capabilities
27
+ WEB_FETCH: 'web_fetch',
28
+ TODO: 'todo',
29
+ HANDOFF: 'handoff',
30
+
31
+ // Vision capabilities
32
+ SCREENSHOT: 'screenshot',
33
+ VISUAL_ANALYSIS: 'visual_analysis'
34
+ };
35
+
36
+ class BaseAgent extends EventEmitter {
37
+ constructor(options = {}) {
38
+ super();
39
+
40
+ this.id = options.id || `agent-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
41
+ this.role = options.role || AgentRole.BUILDER;
42
+ this.name = options.name || `${this.role}-agent`;
43
+ this.description = options.description || '';
44
+
45
+ // AI service for LLM calls
46
+ this.aiService = options.aiService;
47
+
48
+ // State manager for persistence
49
+ this.stateManager = options.stateManager;
50
+
51
+ // Orchestrator reference for handoffs
52
+ this.orchestrator = options.orchestrator;
53
+
54
+ // Configuration
55
+ this.maxRecursionDepth = options.maxRecursionDepth || 3;
56
+ this.maxSubCalls = options.maxSubCalls || 10;
57
+ this.currentDepth = 0;
58
+ this.subCallCount = 0;
59
+
60
+ // Capabilities (subclasses override)
61
+ this.capabilities = options.capabilities || [];
62
+
63
+ // Model metadata tracking
64
+ this.modelMetadata = options.modelMetadata || null;
65
+ this.proofChain = [];
66
+ this.toolHistory = [];
67
+ this.metrics = {
68
+ totalCalls: 0,
69
+ successfulCalls: 0,
70
+ failedCalls: 0,
71
+ avgResponseTimeMs: 0,
72
+ tokenUsage: { prompt: 0, completion: 0 }
73
+ };
74
+
75
+ // Operating contract
76
+ this.contract = {
77
+ noGuessing: true,
78
+ preserveFunctionality: true,
79
+ modularity: true,
80
+ leastPrivilege: true,
81
+ recursionLimits: true,
82
+ security: true,
83
+ backgroundHygiene: true
84
+ };
85
+
86
+ // Conversation history for context
87
+ this.conversationHistory = [];
88
+
89
+ // Active processes (for background hygiene)
90
+ this.activeProcesses = new Map();
91
+ }
92
+
93
+ // ===== Core Methods (to be overridden by subclasses) =====
94
+
95
+ async process(task, context = {}) {
96
+ throw new Error('process() must be implemented by subclass');
97
+ }
98
+
99
+ getSystemPrompt() {
100
+ throw new Error('getSystemPrompt() must be implemented by subclass');
101
+ }
102
+
103
+ // ===== Common Functionality =====
104
+
105
+ async chat(message, options = {}) {
106
+ if (!this.aiService) {
107
+ throw new Error('AI service not configured');
108
+ }
109
+
110
+ // Add to conversation history
111
+ this.conversationHistory.push({
112
+ role: 'user',
113
+ content: message,
114
+ timestamp: new Date().toISOString()
115
+ });
116
+
117
+ const systemPrompt = this.getSystemPrompt();
118
+ const response = await this.aiService.chat(message, {
119
+ systemPrompt,
120
+ history: this.conversationHistory,
121
+ model: options.model,
122
+ ...options
123
+ });
124
+
125
+ // Add response to history
126
+ this.conversationHistory.push({
127
+ role: 'assistant',
128
+ content: response.text,
129
+ timestamp: new Date().toISOString()
130
+ });
131
+
132
+ return response;
133
+ }
134
+
135
+ // ===== Tool Methods =====
136
+
137
+ async search(query, options = {}) {
138
+ this.emit('tool:search', { query, options });
139
+
140
+ // Implementation depends on available tools
141
+ return {
142
+ results: [],
143
+ query,
144
+ timestamp: new Date().toISOString()
145
+ };
146
+ }
147
+
148
+ async read(filePath, options = {}) {
149
+ const fs = require('fs');
150
+
151
+ if (!fs.existsSync(filePath)) {
152
+ return { error: `File not found: ${filePath}` };
153
+ }
154
+
155
+ const content = fs.readFileSync(filePath, 'utf-8');
156
+ this.emit('tool:read', { filePath, lines: content.split('\n').length });
157
+
158
+ return {
159
+ content,
160
+ filePath,
161
+ lines: content.split('\n').length
162
+ };
163
+ }
164
+
165
+ async edit(filePath, changes, options = {}) {
166
+ if (!this.capabilities.includes(AgentCapabilities.EDIT)) {
167
+ return { error: 'Agent does not have edit capability' };
168
+ }
169
+
170
+ this.emit('tool:edit', { filePath, changes });
171
+
172
+ // Actual edit implementation would go here
173
+ return {
174
+ success: true,
175
+ filePath,
176
+ changes
177
+ };
178
+ }
179
+
180
+ async execute(command, options = {}) {
181
+ const { exec, spawn } = require('child_process');
182
+ const { promisify } = require('util');
183
+ const execAsync = promisify(exec);
184
+
185
+ this.emit('tool:execute', { command, options });
186
+
187
+ try {
188
+ if (options.background) {
189
+ // Background process with PID tracking
190
+ const child = spawn(command, [], {
191
+ shell: true,
192
+ detached: true,
193
+ stdio: ['ignore', 'pipe', 'pipe']
194
+ });
195
+
196
+ const pid = child.pid;
197
+ this.activeProcesses.set(pid, { command, startedAt: new Date().toISOString() });
198
+
199
+ return {
200
+ pid,
201
+ command,
202
+ status: 'running'
203
+ };
204
+ }
205
+
206
+ const { stdout, stderr } = await execAsync(command, {
207
+ timeout: options.timeout || 60000,
208
+ maxBuffer: options.maxBuffer || 10 * 1024 * 1024
209
+ });
210
+
211
+ return {
212
+ stdout,
213
+ stderr,
214
+ success: true
215
+ };
216
+ } catch (error) {
217
+ return {
218
+ error: error.message,
219
+ stdout: error.stdout,
220
+ stderr: error.stderr,
221
+ success: false
222
+ };
223
+ }
224
+ }
225
+
226
+ // ===== Handoff Methods =====
227
+
228
+ async handoff(targetRole, context, message) {
229
+ if (!this.orchestrator) {
230
+ throw new Error('Orchestrator not configured for handoffs');
231
+ }
232
+
233
+ this.emit('handoff', {
234
+ from: this.role,
235
+ to: targetRole,
236
+ context,
237
+ message
238
+ });
239
+
240
+ // Record handoff in state
241
+ if (this.stateManager && context.sessionId) {
242
+ this.stateManager.recordHandoff(
243
+ context.sessionId,
244
+ this.role,
245
+ targetRole,
246
+ { message, timestamp: new Date().toISOString() }
247
+ );
248
+ }
249
+
250
+ return this.orchestrator.executeHandoff(this, targetRole, context, message);
251
+ }
252
+
253
+ handoffToSupervisor(context, message) {
254
+ return this.handoff(AgentRole.SUPERVISOR, context, message);
255
+ }
256
+
257
+ handoffToBuilder(context, message) {
258
+ return this.handoff(AgentRole.BUILDER, context, message);
259
+ }
260
+
261
+ handoffToVerifier(context, message) {
262
+ return this.handoff(AgentRole.VERIFIER, context, message);
263
+ }
264
+
265
+ // ===== Recursion Control =====
266
+
267
+ checkRecursionLimits() {
268
+ if (this.currentDepth >= this.maxRecursionDepth) {
269
+ return {
270
+ allowed: false,
271
+ reason: `Max recursion depth (${this.maxRecursionDepth}) reached`
272
+ };
273
+ }
274
+
275
+ if (this.subCallCount >= this.maxSubCalls) {
276
+ return {
277
+ allowed: false,
278
+ reason: `Max sub-calls (${this.maxSubCalls}) reached`
279
+ };
280
+ }
281
+
282
+ return { allowed: true };
283
+ }
284
+
285
+ enterRecursion() {
286
+ this.currentDepth++;
287
+ this.subCallCount++;
288
+ return this.currentDepth;
289
+ }
290
+
291
+ exitRecursion() {
292
+ this.currentDepth = Math.max(0, this.currentDepth - 1);
293
+ return this.currentDepth;
294
+ }
295
+
296
+ // ===== Logging & Proofs =====
297
+
298
+ log(level, message, data = {}) {
299
+ const entry = {
300
+ timestamp: new Date().toISOString(),
301
+ agent: this.id,
302
+ role: this.role,
303
+ level,
304
+ message,
305
+ data
306
+ };
307
+
308
+ this.emit('log', entry);
309
+
310
+ if (level === 'error') {
311
+ console.error(`[${this.role}] ${message}`, data);
312
+ } else {
313
+ console.log(`[${this.role}] ${message}`, data);
314
+ }
315
+
316
+ return entry;
317
+ }
318
+
319
+ addProof(type, content, source = null) {
320
+ const proof = {
321
+ type,
322
+ content,
323
+ source,
324
+ timestamp: new Date().toISOString(),
325
+ agentId: this.id
326
+ };
327
+
328
+ this.emit('proof', proof);
329
+ return proof;
330
+ }
331
+
332
+ addStructuredProof(proof) {
333
+ const structuredProof = {
334
+ id: `proof-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
335
+ ...proof,
336
+ timestamp: new Date().toISOString(),
337
+ agentId: this.id,
338
+ agentRole: this.role,
339
+ modelMetadata: this.modelMetadata
340
+ };
341
+
342
+ this.proofChain.push(structuredProof);
343
+ this.emit('proof', structuredProof);
344
+ return structuredProof;
345
+ }
346
+
347
+ recordToolExecution(toolName, input, output, durationMs, success) {
348
+ this.toolHistory.push({
349
+ id: `tool-${Date.now()}`,
350
+ toolName,
351
+ input,
352
+ output: success ? output : null,
353
+ error: success ? null : output,
354
+ durationMs,
355
+ success,
356
+ timestamp: new Date().toISOString()
357
+ });
358
+
359
+ this.metrics.totalCalls++;
360
+ if (success) {
361
+ this.metrics.successfulCalls++;
362
+ } else {
363
+ this.metrics.failedCalls++;
364
+ }
365
+
366
+ // Update rolling average
367
+ const totalTime = this.metrics.avgResponseTimeMs * (this.metrics.totalCalls - 1) + durationMs;
368
+ this.metrics.avgResponseTimeMs = totalTime / this.metrics.totalCalls;
369
+ }
370
+
371
+ // ===== State Management =====
372
+
373
+ getState() {
374
+ return {
375
+ id: this.id,
376
+ role: this.role,
377
+ name: this.name,
378
+ currentDepth: this.currentDepth,
379
+ subCallCount: this.subCallCount,
380
+ activeProcesses: Array.from(this.activeProcesses.entries()),
381
+ conversationLength: this.conversationHistory.length,
382
+ modelMetadata: this.modelMetadata,
383
+ proofChainLength: this.proofChain.length,
384
+ metrics: this.metrics,
385
+ lastActivity: new Date().toISOString()
386
+ };
387
+ }
388
+
389
+ reset() {
390
+ this.conversationHistory = [];
391
+ this.currentDepth = 0;
392
+ this.subCallCount = 0;
393
+ this.activeProcesses.clear();
394
+ this.proofChain = [];
395
+ this.toolHistory = [];
396
+ this.metrics = {
397
+ totalCalls: 0,
398
+ successfulCalls: 0,
399
+ failedCalls: 0,
400
+ avgResponseTimeMs: 0,
401
+ tokenUsage: { prompt: 0, completion: 0 }
402
+ };
403
+ }
404
+ }
405
+
406
+ module.exports = {
407
+ BaseAgent,
408
+ AgentRole,
409
+ AgentCapabilities
410
+ };