testchimp-runner-core 0.0.35 → 0.0.36

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/package.json +6 -1
  2. package/plandocs/BEFORE_AFTER_VERIFICATION.md +0 -148
  3. package/plandocs/COORDINATE_MODE_DIAGNOSIS.md +0 -144
  4. package/plandocs/CREDIT_CALLBACK_ARCHITECTURE.md +0 -253
  5. package/plandocs/HUMAN_LIKE_IMPROVEMENTS.md +0 -642
  6. package/plandocs/IMPLEMENTATION_STATUS.md +0 -108
  7. package/plandocs/INTEGRATION_COMPLETE.md +0 -322
  8. package/plandocs/MULTI_AGENT_ARCHITECTURE_REVIEW.md +0 -844
  9. package/plandocs/ORCHESTRATOR_MVP_SUMMARY.md +0 -539
  10. package/plandocs/PHASE1_ABSTRACTION_COMPLETE.md +0 -241
  11. package/plandocs/PHASE1_FINAL_STATUS.md +0 -210
  12. package/plandocs/PHASE_1_COMPLETE.md +0 -165
  13. package/plandocs/PHASE_1_SUMMARY.md +0 -184
  14. package/plandocs/PLANNING_SESSION_SUMMARY.md +0 -372
  15. package/plandocs/PROMPT_OPTIMIZATION_ANALYSIS.md +0 -120
  16. package/plandocs/PROMPT_SANITY_CHECK.md +0 -120
  17. package/plandocs/SCRIPT_CLEANUP_FEATURE.md +0 -201
  18. package/plandocs/SCRIPT_GENERATION_ARCHITECTURE.md +0 -364
  19. package/plandocs/SELECTOR_IMPROVEMENTS.md +0 -139
  20. package/plandocs/SESSION_SUMMARY_v0.0.33.md +0 -151
  21. package/plandocs/TROUBLESHOOTING_SESSION.md +0 -72
  22. package/plandocs/VISION_DIAGNOSTICS_IMPROVEMENTS.md +0 -336
  23. package/plandocs/VISUAL_AGENT_EVOLUTION_PLAN.md +0 -396
  24. package/plandocs/WHATS_NEW_v0.0.33.md +0 -183
  25. package/plandocs/exploratory-mode-support-v2.plan.md +0 -953
  26. package/plandocs/exploratory-mode-support.plan.md +0 -928
  27. package/plandocs/journey-id-tracking-addendum.md +0 -227
  28. package/releasenotes/RELEASE_0.0.26.md +0 -165
  29. package/releasenotes/RELEASE_0.0.27.md +0 -236
  30. package/releasenotes/RELEASE_0.0.28.md +0 -286
  31. package/src/auth-config.ts +0 -84
  32. package/src/credit-usage-service.ts +0 -188
  33. package/src/env-loader.ts +0 -103
  34. package/src/execution-service.ts +0 -996
  35. package/src/file-handler.ts +0 -104
  36. package/src/index.ts +0 -432
  37. package/src/llm-facade.ts +0 -821
  38. package/src/llm-provider.ts +0 -53
  39. package/src/model-constants.ts +0 -35
  40. package/src/orchestrator/decision-parser.ts +0 -139
  41. package/src/orchestrator/index.ts +0 -58
  42. package/src/orchestrator/orchestrator-agent.ts +0 -1282
  43. package/src/orchestrator/orchestrator-prompts.ts +0 -786
  44. package/src/orchestrator/page-som-handler.ts +0 -1565
  45. package/src/orchestrator/som-types.ts +0 -188
  46. package/src/orchestrator/tool-registry.ts +0 -184
  47. package/src/orchestrator/tools/check-page-ready.ts +0 -75
  48. package/src/orchestrator/tools/extract-data.ts +0 -92
  49. package/src/orchestrator/tools/index.ts +0 -15
  50. package/src/orchestrator/tools/inspect-page.ts +0 -42
  51. package/src/orchestrator/tools/recall-history.ts +0 -72
  52. package/src/orchestrator/tools/refresh-som-markers.ts +0 -69
  53. package/src/orchestrator/tools/take-screenshot.ts +0 -128
  54. package/src/orchestrator/tools/verify-action-result.ts +0 -159
  55. package/src/orchestrator/tools/view-previous-screenshot.ts +0 -103
  56. package/src/orchestrator/types.ts +0 -291
  57. package/src/playwright-mcp-service.ts +0 -224
  58. package/src/progress-reporter.ts +0 -144
  59. package/src/prompts.ts +0 -842
  60. package/src/providers/backend-proxy-llm-provider.ts +0 -91
  61. package/src/providers/local-llm-provider.ts +0 -38
  62. package/src/scenario-service.ts +0 -252
  63. package/src/scenario-worker-class.ts +0 -1110
  64. package/src/script-utils.ts +0 -203
  65. package/src/types.ts +0 -239
  66. package/src/utils/browser-utils.ts +0 -348
  67. package/src/utils/coordinate-converter.ts +0 -162
  68. package/src/utils/page-info-retry.ts +0 -65
  69. package/src/utils/page-info-utils.ts +0 -285
  70. package/testchimp-runner-core-0.0.35.tgz +0 -0
  71. package/tsconfig.json +0 -19
@@ -1,91 +0,0 @@
1
- /**
2
- * Backend Proxy LLM Provider
3
- * Calls backend proxy API with authentication
4
- * Used by VS Extension and GitHub Runner
5
- */
6
-
7
- import axios from 'axios';
8
- import { LLMProvider, LLMRequest, LLMResponse } from '../llm-provider';
9
- import { AuthConfig, getAuthHeaders } from '../auth-config';
10
-
11
- /**
12
- * Default LLM provider that calls backend proxy
13
- * Converts camelCase requests to snake_case for backend API
14
- */
15
- export class BackendProxyLLMProvider implements LLMProvider {
16
- private authConfig?: AuthConfig;
17
- private backendUrl: string;
18
- private logger?: (message: string, level?: 'log' | 'error' | 'warn') => void;
19
-
20
- constructor(authConfig?: AuthConfig, backendUrl?: string) {
21
- this.authConfig = authConfig;
22
- this.backendUrl = backendUrl || 'https://featureservice.testchimp.io';
23
- }
24
-
25
- setLogger(logger: (message: string, level?: 'log' | 'error' | 'warn') => void): void {
26
- this.logger = logger;
27
- }
28
-
29
- async callLLM(request: LLMRequest): Promise<LLMResponse> {
30
- if (!this.authConfig) {
31
- throw new Error('Authentication required for backend proxy LLM provider');
32
- }
33
-
34
- const headers = getAuthHeaders(this.authConfig);
35
-
36
- // Convert camelCase to snake_case for backend API (proto format)
37
- const backendRequest = {
38
- model: request.model,
39
- system_prompt: request.systemPrompt,
40
- user_prompt: request.userPrompt,
41
- image_url: request.imageUrl
42
- };
43
-
44
- const url = `${this.backendUrl}/localagent/call_llm`;
45
-
46
- try {
47
- const response = await axios.post(
48
- url,
49
- backendRequest,
50
- { headers, timeout: 300000 }
51
- );
52
-
53
- // Calculate token usage (heuristic: 4 chars = 1 token)
54
- const inputText = `${request.systemPrompt || ''}\n${request.userPrompt || ''}`;
55
- const inputTokens = Math.ceil(inputText.length / 4);
56
-
57
- // Add image tokens if present (for vision models)
58
- let imageTokens = 0;
59
- if (request.imageUrl) {
60
- imageTokens = this.estimateImageTokens(request.imageUrl);
61
- }
62
-
63
- const outputTokens = Math.ceil((response.data.answer || '').length / 4);
64
-
65
- return {
66
- answer: response.data.answer,
67
- usage: {
68
- inputTokens: inputTokens + imageTokens,
69
- outputTokens
70
- }
71
- };
72
- } catch (error: any) {
73
- this.logger?.(`LLM call failed: ${error}`, 'error');
74
- throw error;
75
- }
76
- }
77
-
78
- /**
79
- * Estimate image token cost based on dimensions
80
- * For gpt-4.1-mini: patches × 1.62, capped at 1536
81
- */
82
- private estimateImageTokens(imageDataUrl: string): number {
83
- // For simplicity, estimate common screenshot sizes
84
- // Viewport (1920x1080): ~1452 tokens (after multiplier and cap)
85
- // Full page (1920x3000+): ~1536 tokens (capped)
86
-
87
- // Conservative estimate: assume viewport screenshot
88
- return 1500; // ~1452-1536 tokens for typical screenshot
89
- }
90
- }
91
-
@@ -1,38 +0,0 @@
1
- /**
2
- * Local LLM Provider
3
- * Calls LLM directly via callback (not via backend proxy)
4
- * For future use by Script Service (Phase 2)
5
- */
6
-
7
- import { LLMProvider, LLMRequest, LLMResponse } from '../llm-provider';
8
-
9
- /**
10
- * Local LLM provider that calls LLM directly via callback
11
- * Allows Script Service to use its own OpenAI integration
12
- */
13
- export class LocalLLMProvider implements LLMProvider {
14
- private llmCallback: (request: LLMRequest) => Promise<string>;
15
- private logger?: (message: string, level?: 'log' | 'error' | 'warn') => void;
16
-
17
- /**
18
- * @param llmCallback Function that calls LLM (provided by environment)
19
- */
20
- constructor(llmCallback: (request: LLMRequest) => Promise<string>) {
21
- this.llmCallback = llmCallback;
22
- }
23
-
24
- setLogger(logger: (message: string, level?: 'log' | 'error' | 'warn') => void): void {
25
- this.logger = logger;
26
- }
27
-
28
- async callLLM(request: LLMRequest): Promise<LLMResponse> {
29
- try {
30
- const answer = await this.llmCallback(request);
31
- return { answer };
32
- } catch (error) {
33
- this.logger?.(`Local LLM call failed: ${error}`, 'error');
34
- throw error;
35
- }
36
- }
37
- }
38
-
@@ -1,252 +0,0 @@
1
- import { EventEmitter } from 'events';
2
- import dotenv from 'dotenv';
3
- import { ScenarioJob, ScenarioRunJob, ScenarioResponse, PlaywrightConfig } from './types';
4
- import { ScenarioWorker } from './scenario-worker-class';
5
- import { FileHandler, NoOpFileHandler } from './file-handler';
6
- import { AuthConfig } from './auth-config';
7
- import { CreditUsageService } from './credit-usage-service';
8
- import { LLMProvider } from './llm-provider';
9
- import { ProgressReporter } from './progress-reporter';
10
- import { AgentConfig } from './orchestrator';
11
-
12
- // Load environment variables
13
- dotenv.config();
14
-
15
- /**
16
- * Service for processing scenarios using LLM + Playwright
17
- */
18
- export class ScenarioService extends EventEmitter {
19
- private workers: ScenarioWorker[] = [];
20
- private jobQueue: ScenarioRunJob[] = [];
21
- private busyWorkers: Set<ScenarioWorker> = new Set();
22
- private maxWorkers: number;
23
- private fileHandler: FileHandler;
24
- private authConfig: AuthConfig | null;
25
- private backendUrl?: string;
26
- private creditUsageService: CreditUsageService;
27
- private logger?: (message: string, level?: 'log' | 'error' | 'warn') => void;
28
- private llmProvider?: LLMProvider;
29
- private progressReporter?: ProgressReporter;
30
- private useOrchestrator: boolean;
31
- private orchestratorConfig?: Partial<AgentConfig>;
32
- private debugMode: boolean;
33
- private outputChannel?: any; // VS Code OutputChannel type
34
-
35
- constructor(
36
- maxWorkers: number = 2,
37
- fileHandler?: FileHandler,
38
- llmProvider?: LLMProvider,
39
- progressReporter?: ProgressReporter,
40
- authConfig?: AuthConfig,
41
- backendUrl?: string,
42
- options?: {
43
- useOrchestrator?: boolean;
44
- orchestratorConfig?: Partial<AgentConfig>;
45
- debugMode?: boolean;
46
- }
47
- ) {
48
- super();
49
- this.maxWorkers = maxWorkers;
50
- this.fileHandler = fileHandler || new NoOpFileHandler();
51
- this.llmProvider = llmProvider;
52
- this.progressReporter = progressReporter;
53
- this.authConfig = authConfig || null;
54
- this.backendUrl = backendUrl;
55
- this.creditUsageService = new CreditUsageService(authConfig, backendUrl);
56
- this.useOrchestrator = options?.useOrchestrator || false;
57
- this.orchestratorConfig = options?.orchestratorConfig;
58
- this.debugMode = options?.debugMode || false;
59
- }
60
-
61
- /**
62
- * Set a logger callback for capturing execution logs
63
- */
64
- setLogger(logger: (message: string, level?: 'log' | 'error' | 'warn') => void): void {
65
- this.logger = logger;
66
- }
67
-
68
- /**
69
- * Set output channel for worker logs (VS Code OutputChannel)
70
- */
71
- setOutputChannel(outputChannel: any): void {
72
- this.outputChannel = outputChannel;
73
- }
74
-
75
- /**
76
- * Log a message using the configured logger
77
- */
78
- private log(message: string, level: 'log' | 'error' | 'warn' = 'log'): void {
79
- if (this.logger) {
80
- this.logger(message, level);
81
- }
82
- // No console fallback - logs are routed to consumer
83
- }
84
-
85
- private async initializeWorkers(): Promise<void> {
86
- for (let i = 0; i < this.maxWorkers; i++) {
87
- await this.createWorker();
88
- }
89
- }
90
-
91
- private async createWorker(): Promise<void> {
92
- // Pass providers and orchestrator options to worker
93
- const worker = new ScenarioWorker(
94
- this.fileHandler,
95
- this.llmProvider,
96
- this.progressReporter,
97
- this.authConfig || undefined,
98
- this.backendUrl,
99
- {
100
- useOrchestrator: this.useOrchestrator,
101
- orchestratorConfig: this.orchestratorConfig,
102
- debugMode: this.debugMode
103
- },
104
- this.outputChannel // Pass outputChannel for log routing
105
- );
106
- await worker.initialize();
107
-
108
- // Forward log events from worker to service listeners
109
- worker.on('log', (jobId: string, message: string) => {
110
- this.emit('jobLog', jobId, message);
111
- });
112
-
113
- this.workers.push(worker);
114
- // Internal initialization - no need to log worker details
115
- }
116
-
117
- async initialize(): Promise<void> {
118
- // Wait for workers to be initialized
119
- await this.initializeWorkers();
120
- // Internal initialization - consumer doesn't need to see this
121
- }
122
-
123
- processScenario(
124
- scenario: string,
125
- testName?: string,
126
- config?: PlaywrightConfig,
127
- model?: string,
128
- scenarioFileName?: string,
129
- existingBrowser?: any,
130
- existingContext?: any,
131
- existingPage?: any
132
- ): string {
133
- const jobId = `scenario_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
134
-
135
- // Add job to queue
136
- const job: ScenarioRunJob = {
137
- id: jobId,
138
- scenario,
139
- testName,
140
- playwrightConfig: config,
141
- model,
142
- scenarioFileName,
143
- existingBrowser,
144
- existingContext,
145
- existingPage
146
- };
147
-
148
- this.jobQueue.push(job);
149
- this.processNextJob();
150
-
151
- return jobId; // Return job ID for tracking
152
- }
153
-
154
- private async processNextJob(): Promise<void> {
155
- if (this.jobQueue.length === 0) {
156
- return;
157
- }
158
-
159
- this.log(`[ScenarioService] Processing next job. Queue length: ${this.jobQueue.length}, Workers: ${this.workers.length}, Busy workers: ${this.busyWorkers.size}`);
160
-
161
- // Find available worker (proper load balancing)
162
- const availableWorker = this.workers.find(worker => !this.busyWorkers.has(worker));
163
- if (!availableWorker) {
164
- this.log('[ScenarioService] No available workers, waiting...');
165
- return; // All workers busy, wait for one to become available
166
- }
167
-
168
- const job = this.jobQueue.shift();
169
- if (!job) {
170
- return;
171
- }
172
-
173
- this.log(`[ScenarioService] Processing job ${job.id} with worker`);
174
-
175
- // Mark worker as busy
176
- this.busyWorkers.add(availableWorker);
177
-
178
- try {
179
- // Process job directly with worker
180
- const result = await availableWorker.processScenarioJob(job);
181
- this.log(`[ScenarioService] Job ${job.id} completed with result: ${JSON.stringify(result)}`);
182
- this.handleJobResult(job.id, result);
183
- } catch (error) {
184
- this.log(`Error processing job with worker: ${error}`, 'error');
185
- this.emit('jobError', job.id, error);
186
- // Put job back in queue if it failed
187
- this.jobQueue.unshift(job);
188
- } finally {
189
- // Mark worker as available again
190
- this.busyWorkers.delete(availableWorker);
191
- // Process next job
192
- this.processNextJob();
193
- }
194
- }
195
-
196
- private handleJobResult(jobId: string, result: ScenarioResponse): void {
197
- // Report credit usage for successful script generation
198
- if (result.success) {
199
- this.creditUsageService.reportScriptGenerationCredit(jobId).catch(error => {
200
- this.log(`Failed to report credit usage for script generation (job: ${jobId}): ${error}`, 'warn');
201
- });
202
- }
203
-
204
- // Emit result event
205
- this.emit('jobComplete', jobId, result);
206
-
207
- // Mark worker as available and process next job
208
- this.busyWorkers.clear(); // Simple approach - clear all busy workers
209
- this.processNextJob();
210
- }
211
-
212
- private handleJobError(jobId: string, error: string): void {
213
- // Emit error event
214
- this.emit('jobError', jobId, new Error(error));
215
-
216
- // Mark worker as available and process next job
217
- this.busyWorkers.clear(); // Simple approach - clear all busy workers
218
- this.processNextJob();
219
- }
220
-
221
- /**
222
- * Execute exploration mode using orchestrator
223
- * Requires orchestrator to be enabled via useOrchestrator option
224
- */
225
- async executeExploration(page: any, explorationConfig: any, jobId: string): Promise<any> {
226
- if (!this.useOrchestrator) {
227
- throw new Error('Exploration mode requires orchestrator to be enabled');
228
- }
229
-
230
- // Get an available worker (or create one if needed)
231
- let worker = this.workers.find(w => !this.busyWorkers.has(w));
232
- if (!worker) {
233
- await this.createWorker();
234
- worker = this.workers[this.workers.length - 1];
235
- }
236
-
237
- // Execute exploration via worker's orchestrator
238
- return worker.executeExploration(page, explorationConfig, jobId);
239
- }
240
-
241
- async shutdown(): Promise<void> {
242
- this.log('Shutting down scenario service...');
243
-
244
- // Cleanup all workers
245
- const cleanupPromises = this.workers.map(worker => worker.cleanup());
246
- await Promise.all(cleanupPromises);
247
-
248
- this.workers = [];
249
- this.busyWorkers.clear();
250
- this.log('Scenario service shutdown complete');
251
- }
252
- }