@vostride/agent-qa-dashboard 0.1.21 → 0.2.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.
@@ -1,1168 +0,0 @@
1
- import { Server, IncomingMessage, ServerResponse } from 'node:http';
2
- import { RunAttributes, RunArtifactKind, RunArtifactStageInput, RunArtifactPayload, RunArtifactFinalizeInput, LogEntry, ResolvedWorkspacePaths, ModelConfig, ResolvedAppiumExecutable, SecretStore, SecretRedactor, HookDefinition, ConsoleLogEntry, NetworkLogEntry, StepAnnotation, StepPhaseEvent, StepResult, AuthStateMetadata, buildAnalyticsEvent, captureAnalytics, resolveAnalyticsStandardProperties } from '@vostride/agent-qa-core';
3
- import { LocalMcpEndpointConfig, LocalMcpTransport } from '@vostride/agent-qa-mcp';
4
- import { Document } from 'yaml';
5
- import { EventEmitter } from 'node:events';
6
- import { ChildProcess } from 'node:child_process';
7
-
8
- interface RunRow {
9
- id: string;
10
- name: string;
11
- filePath: string | null;
12
- status: string;
13
- priority: number;
14
- duration: number;
15
- attributes: RunAttributes;
16
- environment: string | null;
17
- metadata: Record<string, unknown> | null;
18
- startedAt: string | null;
19
- endedAt: string | null;
20
- videoPath: string | null;
21
- failureSummary: string | null;
22
- errorLog: string | null;
23
- memoryLog: string | null;
24
- testId: string | null;
25
- suiteId: string | null;
26
- platform: string;
27
- testFileContent: string | null;
28
- modelName: string | null;
29
- llmProvider: string | null;
30
- parallel: boolean;
31
- parentRunId: string | null;
32
- attemptNumber: number;
33
- retryCount: number;
34
- maxRetries: number;
35
- createdAt: string;
36
- }
37
- interface RunArtifactRow {
38
- runId: string;
39
- kind: RunArtifactKind;
40
- schemaVersion: number;
41
- payload: RunArtifactPayload;
42
- finalizedAt: string | null;
43
- createdAt: string;
44
- updatedAt: string;
45
- }
46
- interface RunArtifactBundle {
47
- artifact: RunArtifactRow | null;
48
- children: Array<{
49
- run: RunRow;
50
- artifact: RunArtifactRow | null;
51
- }>;
52
- }
53
- interface StepRow {
54
- id: string;
55
- runId: string;
56
- name: string;
57
- status: string;
58
- duration: number;
59
- action: unknown | null;
60
- observation: string | null;
61
- reasoning: string | null;
62
- plannedAction: unknown | null;
63
- result: string | null;
64
- error: string | null;
65
- screenshotPath: string | null;
66
- screenshotBeforePath: string | null;
67
- healingAttempts: unknown[] | null;
68
- retryCount: number;
69
- capturedVariables: Record<string, string> | null;
70
- stepOrder: number;
71
- annotationData: unknown | null;
72
- healingScreenshotPaths: string[] | null;
73
- accessibilityViolations: unknown[] | null;
74
- confidence: number | null;
75
- promptTokens: number;
76
- completionTokens: number;
77
- totalTokens: number;
78
- subActionsData: unknown[] | null;
79
- consoleLogs: unknown[] | null;
80
- networkLogs: unknown[] | null;
81
- variableSnapshot: Record<string, {
82
- value: string;
83
- source: string;
84
- }> | null;
85
- originalStepName: string | null;
86
- screenContextBefore: string | null;
87
- screenContextAfter: string | null;
88
- createdAt: string;
89
- }
90
- interface ReasoningTraceRow {
91
- id: string;
92
- stepId: string;
93
- observeText: string | null;
94
- observeDuration: number | null;
95
- planReasoning: string | null;
96
- planConfidence: number | null;
97
- planAction: unknown | null;
98
- planDuration: number | null;
99
- executeAction: unknown | null;
100
- executeDuration: number | null;
101
- verifyReasoning: string | null;
102
- verifySuccess: boolean | null;
103
- verifyDuration: number | null;
104
- healAttempts: unknown[] | null;
105
- totalDuration: number | null;
106
- screenStateBefore: string | null;
107
- screenStateAfter: string | null;
108
- createdAt: string;
109
- }
110
- interface ExecutionLogRow {
111
- id: string;
112
- runId: string;
113
- stepId: string | null;
114
- type: 'hook' | 'appium-script' | 'runjs';
115
- name: string;
116
- hookId: string | null;
117
- phase: 'setup' | 'teardown' | 'inline';
118
- status: 'passed' | 'failed';
119
- duration: number;
120
- stdout: string | null;
121
- stderr: string | null;
122
- returnData: unknown | null;
123
- variables: Record<string, string> | null;
124
- createdAt: string;
125
- }
126
- interface InsertExecutionLogInput {
127
- id: string;
128
- runId: string;
129
- stepId?: string | null;
130
- type: 'hook' | 'appium-script' | 'runjs';
131
- name: string;
132
- hookId?: string | null;
133
- phase: 'setup' | 'teardown' | 'inline';
134
- status: 'passed' | 'failed';
135
- duration: number;
136
- stdout?: string | null;
137
- stderr?: string | null;
138
- returnData?: unknown | null;
139
- variables?: Record<string, string> | null;
140
- }
141
- interface RunsFilter {
142
- status?: string;
143
- name?: string;
144
- platform?: string;
145
- from?: string;
146
- to?: string;
147
- attributePredicates?: AttributePredicate[];
148
- limit?: number;
149
- offset?: number;
150
- }
151
- interface StatsOptions {
152
- from?: string;
153
- to?: string;
154
- attributePredicates?: AttributePredicate[];
155
- }
156
- type InsightsBreakdownDimension = 'test' | 'suite' | 'platform';
157
- interface InsightsBreakdownRow {
158
- key: string;
159
- label: string;
160
- runs: number;
161
- passRate: number;
162
- flakeRate: number;
163
- avgDuration: number;
164
- passed: number;
165
- failed: number;
166
- filePath?: string;
167
- suiteId?: string;
168
- }
169
- interface DeleteRunResult {
170
- deleted: boolean;
171
- deletedRunIds: string[];
172
- screenshotPaths: string[];
173
- videoPaths: string[];
174
- }
175
- interface AttributePredicate {
176
- key: string;
177
- value: string;
178
- mode: 'exact' | 'regex';
179
- }
180
- interface AttributeKeySuggestion {
181
- key: string;
182
- count: number;
183
- }
184
- interface AttributeValueSuggestion {
185
- value: string;
186
- count: number;
187
- }
188
- declare class DashboardDatabase {
189
- private db;
190
- constructor({ dbPath }?: {
191
- dbPath?: string;
192
- });
193
- private runMigrations;
194
- insertRun(run: {
195
- id?: string;
196
- name: string;
197
- filePath?: string;
198
- status: string;
199
- duration: number;
200
- attributes?: RunAttributes;
201
- environment?: string;
202
- metadata?: Record<string, unknown>;
203
- startedAt: string;
204
- endedAt: string;
205
- videoPath?: string;
206
- failureSummary?: string;
207
- platform?: string;
208
- testFileContent?: string;
209
- modelName?: string;
210
- llmProvider?: string;
211
- parentRunId?: string;
212
- attemptNumber?: number;
213
- retryCount?: number;
214
- maxRetries?: number;
215
- testId?: string;
216
- suiteId?: string;
217
- }): string;
218
- updateRun(id: string, updates: {
219
- name?: string;
220
- status?: string;
221
- duration?: number;
222
- startedAt?: string;
223
- endedAt?: string;
224
- failureSummary?: string;
225
- errorLog?: string;
226
- memoryLog?: string;
227
- videoPath?: string;
228
- attributes?: RunAttributes;
229
- platform?: string;
230
- testId?: string;
231
- suiteId?: string;
232
- }): void;
233
- updateRunMetadata(id: string, updates: {
234
- attributes?: RunAttributes;
235
- metadata?: Record<string, unknown>;
236
- platform?: string;
237
- testFileContent?: string;
238
- modelName?: string;
239
- llmProvider?: string;
240
- }): void;
241
- insertPendingRun(run: {
242
- id?: string;
243
- name: string;
244
- filePath?: string;
245
- attributes?: RunAttributes;
246
- priority?: number;
247
- platform?: string;
248
- testFileContent?: string;
249
- modelName?: string;
250
- llmProvider?: string;
251
- metadata?: Record<string, unknown>;
252
- parallel?: boolean;
253
- maxRetries?: number;
254
- }): string;
255
- getNextPendingRun(): RunRow | undefined;
256
- getPendingRuns(): RunRow[];
257
- updateRunStatus(id: string, status: string): void;
258
- insertStep(step: {
259
- id?: string;
260
- runId: string;
261
- name: string;
262
- status: string;
263
- duration: number;
264
- action?: unknown;
265
- observation?: string;
266
- reasoning?: string;
267
- plannedAction?: unknown;
268
- result?: string;
269
- error?: string;
270
- screenshotPath?: string;
271
- screenshotBeforePath?: string;
272
- healingAttempts?: unknown[];
273
- retryCount?: number;
274
- capturedVariables?: Record<string, string>;
275
- stepOrder: number;
276
- annotationData?: unknown;
277
- healingScreenshotPaths?: string[];
278
- accessibilityViolations?: unknown[];
279
- confidence?: number;
280
- promptTokens?: number;
281
- completionTokens?: number;
282
- totalTokens?: number;
283
- subActionsData?: unknown[];
284
- consoleLogs?: unknown[];
285
- networkLogs?: unknown[];
286
- variableSnapshot?: Record<string, unknown>;
287
- originalStepName?: string;
288
- screenContextBefore?: string;
289
- screenContextAfter?: string;
290
- }): string;
291
- private appendAttributePredicateConditions;
292
- private applyRegexAttributePredicates;
293
- private queryRunsWithAttributePredicates;
294
- private buildTrendsFromRuns;
295
- getRuns(opts?: RunsFilter): RunRow[];
296
- getRun(id: string): RunRow | undefined;
297
- listRunAttributeKeys(opts?: {
298
- limit?: number;
299
- q?: string;
300
- }): AttributeKeySuggestion[];
301
- listRunAttributeValues(key: string, opts?: {
302
- limit?: number;
303
- q?: string;
304
- }): AttributeValueSuggestion[];
305
- deleteRun(id: string): DeleteRunResult;
306
- getSteps(runId: string): StepRow[];
307
- getCapturedVariableNames(testId: string): string[];
308
- getRunsByParent(parentRunId: string): RunRow[];
309
- insertRunArtifact(input: {
310
- runId: string;
311
- kind?: RunArtifactKind;
312
- payload?: RunArtifactStageInput;
313
- }): RunArtifactRow;
314
- stageRunArtifact(runId: string, patch: RunArtifactStageInput): RunArtifactRow;
315
- finalizeRunArtifact(runId: string, updates?: RunArtifactFinalizeInput): RunArtifactRow;
316
- getRunArtifact(runId: string): RunArtifactRow | null;
317
- getRunArtifactBundle(runId: string): RunArtifactBundle;
318
- updateRunRetryInfo(id: string, info: {
319
- retryCount: number;
320
- maxRetries: number;
321
- }): void;
322
- private isSuccessfulRunStatus;
323
- private getHealedRunIds;
324
- private summarizeAnalyticsRuns;
325
- private listRunsForInsights;
326
- getStats(opts?: StatsOptions): {
327
- totalRuns: number;
328
- passed: number;
329
- failed: number;
330
- flaky: number;
331
- flakeRate: number;
332
- avgDuration: number;
333
- totalTokens: number;
334
- runs: {
335
- date: string;
336
- passed: number;
337
- failed: number;
338
- healed: number;
339
- duration: number;
340
- }[];
341
- memory: {
342
- runs: number;
343
- added: number;
344
- confirmed: number;
345
- deprecated: number;
346
- deleted: number;
347
- curatorTokens: number;
348
- };
349
- };
350
- getCostStats(opts?: StatsOptions): {
351
- runs: {
352
- runId: string;
353
- name: string;
354
- startedAt: string | null;
355
- promptTokens: number;
356
- completionTokens: number;
357
- totalTokens: number;
358
- }[];
359
- totals: {
360
- promptTokens: number;
361
- completionTokens: number;
362
- totalTokens: number;
363
- };
364
- };
365
- insertTokenEvent(event: {
366
- modelName: string;
367
- promptTokens: number;
368
- completionTokens: number;
369
- source: 'test-run' | 'live-editor';
370
- }): string;
371
- getTokenEventStats(opts?: {
372
- from?: string;
373
- to?: string;
374
- }): {
375
- byModel: {
376
- date: string;
377
- model: string;
378
- promptTokens: number;
379
- completionTokens: number;
380
- }[];
381
- bySource: Record<string, {
382
- promptTokens: number;
383
- completionTokens: number;
384
- }>;
385
- totals: {
386
- promptTokens: number;
387
- completionTokens: number;
388
- };
389
- };
390
- getRunsByTestName(name: string, opts?: {
391
- limit?: number;
392
- offset?: number;
393
- attributePredicates?: AttributePredicate[];
394
- }): RunRow[];
395
- getRunsByTestNameCount(name: string, opts?: {
396
- attributePredicates?: AttributePredicate[];
397
- }): number;
398
- getTestTrends(name: string, opts?: {
399
- from?: string;
400
- attributePredicates?: AttributePredicate[];
401
- }): {
402
- daily: {
403
- date: string;
404
- passed: number;
405
- failed: number;
406
- total: number;
407
- avgDuration: number;
408
- }[];
409
- passRate: number;
410
- totalRuns: number;
411
- avgDuration: number;
412
- };
413
- getRunsBySuiteId(suiteId: string, opts?: {
414
- limit?: number;
415
- offset?: number;
416
- attributePredicates?: AttributePredicate[];
417
- }): RunRow[];
418
- getRunsBySuiteIdCount(suiteId: string, opts?: {
419
- attributePredicates?: AttributePredicate[];
420
- }): number;
421
- getSuiteTrends(suiteId: string, opts?: {
422
- from?: string;
423
- attributePredicates?: AttributePredicate[];
424
- }): {
425
- daily: {
426
- date: string;
427
- passed: number;
428
- failed: number;
429
- total: number;
430
- avgDuration: number;
431
- }[];
432
- passRate: number;
433
- totalRuns: number;
434
- avgDuration: number;
435
- };
436
- getInsightsBreakdown(dimension: InsightsBreakdownDimension, opts?: StatsOptions & {
437
- limit?: number;
438
- }): InsightsBreakdownRow[];
439
- getFlakyTests(opts?: {
440
- minRuns?: number;
441
- limit?: number;
442
- }): {
443
- name: string;
444
- filePath: string | null;
445
- totalRuns: number;
446
- passRate: number;
447
- flakyScore: number;
448
- }[];
449
- getAccessibilitySummary(runId: string): {
450
- enabled: boolean | null;
451
- total: number;
452
- bySeverity: Record<string, number>;
453
- byRule: {
454
- count: number;
455
- impact: string;
456
- ruleId: string;
457
- }[];
458
- stepsWithViolations: number;
459
- scannedSteps: number;
460
- unscannedSteps: number;
461
- totalSteps: number;
462
- };
463
- private getRunAccessibilityEnabled;
464
- getStep(stepId: string): StepRow | undefined;
465
- insertReasoningTrace(trace: {
466
- stepId: string;
467
- observeText?: string;
468
- observeDuration?: number;
469
- planReasoning?: string;
470
- planConfidence?: number;
471
- planAction?: unknown;
472
- planDuration?: number;
473
- executeAction?: unknown;
474
- executeDuration?: number;
475
- verifyReasoning?: string;
476
- verifySuccess?: boolean;
477
- verifyDuration?: number;
478
- healAttempts?: unknown[];
479
- totalDuration?: number;
480
- screenStateBefore?: string;
481
- screenStateAfter?: string;
482
- }): string;
483
- getReasoningTrace(runId: string, stepOrder: number): ReasoningTraceRow | undefined;
484
- insertLogs(entries: LogEntry[]): void;
485
- getLogs(opts?: {
486
- runId?: string;
487
- stepId?: string;
488
- level?: string;
489
- source?: string;
490
- limit?: number;
491
- offset?: number;
492
- }): LogEntry[];
493
- insertExecutionLog(data: InsertExecutionLogInput): void;
494
- getExecutionLogs(filter: {
495
- runId?: string;
496
- stepId?: string;
497
- type?: string;
498
- }): ExecutionLogRow[];
499
- close(): void;
500
- private parseRunAttributes;
501
- private mapRunRow;
502
- private mapRunArtifactRow;
503
- private mapStepRow;
504
- private mapLogRow;
505
- private mapReasoningTraceRow;
506
- }
507
-
508
- interface StartServerOptions {
509
- db: DashboardDatabase;
510
- port?: number;
511
- uiDir?: string;
512
- artifactsDir?: string;
513
- workspacePaths?: ResolvedWorkspacePaths;
514
- configPath?: string;
515
- mcp?: LocalMcpEndpointConfig;
516
- llmConfig?: Pick<ModelConfig, 'provider' | 'model' | 'apiKey' | 'authToken' | 'baseURL' | 'providerHeaders'> & {
517
- screenshotSize?: number;
518
- effectiveResolution?: number;
519
- };
520
- authFetch?: typeof globalThis.fetch;
521
- }
522
- interface McpStartupInfo {
523
- enabled: boolean;
524
- transport: LocalMcpTransport;
525
- host?: string;
526
- port?: number;
527
- path?: string;
528
- url?: string;
529
- }
530
- declare function startServer(opts: StartServerOptions): Promise<{
531
- server: Server;
532
- port: number;
533
- mcp: McpStartupInfo;
534
- close: () => void;
535
- }>;
536
-
537
- interface AppiumLeaseOwner {
538
- runId: string;
539
- platform: 'android' | 'ios';
540
- }
541
- interface AppiumLease extends AppiumLeaseOwner {
542
- acquiredAt: string;
543
- }
544
- declare class AppiumManager {
545
- private process;
546
- private port;
547
- private ready;
548
- private startPromise;
549
- private managed;
550
- private startupTimeoutMs;
551
- private pollIntervalMs;
552
- private anonymousRefCount;
553
- private leases;
554
- private logLevel;
555
- private appiumResolver;
556
- constructor(opts?: {
557
- port?: number;
558
- startupTimeoutMs?: number;
559
- pollIntervalMs?: number;
560
- logLevel?: 'normal' | 'debug';
561
- appiumResolver?: () => ResolvedAppiumExecutable;
562
- });
563
- acquire(): Promise<void>;
564
- release(): void;
565
- acquireLease(owner: AppiumLeaseOwner): Promise<void>;
566
- releaseLease(runId: string, reason?: string): boolean;
567
- releaseAllLeases(reason?: string): string[];
568
- ensureRunning(): Promise<void>;
569
- checkStatus(): Promise<boolean>;
570
- private startAndWait;
571
- private performShutdown;
572
- private maybeShutdownAfterRelease;
573
- shutdown(): void;
574
- getUrl(): string;
575
- getPort(): number;
576
- isManaged(): boolean;
577
- getRefCount(): number;
578
- getLeaseCount(): number;
579
- getLeases(): AppiumLease[];
580
- hasLease(runId: string): boolean;
581
- }
582
-
583
- declare class ConfigManager {
584
- private configPath;
585
- constructor(configPath: string);
586
- read(): Promise<Record<string, unknown>>;
587
- readMasked(): Promise<Record<string, unknown>>;
588
- private sectionPath;
589
- updateSection(section: string, value: Record<string, unknown>): Promise<void>;
590
- replaceSection(section: string, value: Record<string, unknown>): Promise<void>;
591
- replaceSectionRaw(section: string, value: unknown): Promise<void>;
592
- deleteSectionRaw(section: string): Promise<void>;
593
- readDocument(): Promise<Document>;
594
- }
595
-
596
- type LiveSessionLLMConfig = Pick<ModelConfig, 'provider' | 'model' | 'apiKey' | 'authToken' | 'baseURL' | 'providerHeaders'> & {
597
- screenshotSize?: number;
598
- effectiveResolution?: number;
599
- };
600
- interface LiveDraftMetadata {
601
- testName: string;
602
- testContext?: string;
603
- }
604
- interface EntityRef {
605
- type: 'suite' | 'test';
606
- id: string;
607
- }
608
- interface LiveExecutionLog {
609
- id: string;
610
- type: 'hook' | 'appium-script' | 'runjs';
611
- name: string;
612
- hookId?: string | null;
613
- phase: 'setup' | 'teardown' | 'inline';
614
- status: 'passed' | 'failed';
615
- duration: number;
616
- stdout: string | null;
617
- stderr: string | null;
618
- returnData: unknown | null;
619
- variables: Record<string, string> | null;
620
- createdAt: string;
621
- }
622
- interface LiveSubActionData {
623
- index: number;
624
- observation: string;
625
- reasoning: string;
626
- plannedAction: unknown;
627
- result: 'success' | 'failure' | 'in-progress';
628
- error?: string;
629
- screenStateBefore: string;
630
- screenStateAfter?: string;
631
- confidence?: number;
632
- verifierReasoning?: string;
633
- cached: boolean;
634
- tokenUsage?: {
635
- promptTokens: number;
636
- completionTokens: number;
637
- totalTokens: number;
638
- };
639
- phaseDurations?: {
640
- observe?: number;
641
- plan?: number;
642
- execute?: number;
643
- verify?: number;
644
- };
645
- annotation?: StepAnnotation;
646
- screenContextBefore?: string;
647
- screenContextAfter?: string;
648
- data?: unknown;
649
- }
650
- interface LiveStepResultPayload {
651
- status: 'passed' | 'failed' | 'cancelled';
652
- duration?: number;
653
- error?: string;
654
- capturedVariables?: Record<string, string>;
655
- variableSnapshot?: Record<string, {
656
- value: string;
657
- source: string;
658
- }>;
659
- originalStepName?: string;
660
- consoleLogs?: ConsoleLogEntry[];
661
- networkLogs?: NetworkLogEntry[];
662
- executionLogs?: LiveExecutionLog[];
663
- subActionsData?: LiveSubActionData[];
664
- }
665
- interface LiveSuiteHookOwner {
666
- scope: 'suite';
667
- }
668
- interface LiveTestOwner {
669
- scope: 'test';
670
- testExecutionId: string;
671
- testIndex: number;
672
- testId: string;
673
- testName: string;
674
- }
675
- type LiveHookOwner = LiveSuiteHookOwner | LiveTestOwner;
676
- interface LiveHookPayload {
677
- executionId: string;
678
- hookId: string;
679
- hookName: string;
680
- phase: 'setup' | 'teardown';
681
- owner: LiveHookOwner;
682
- status: 'running' | 'passed' | 'failed';
683
- duration?: number;
684
- stdout?: string | null;
685
- stderr?: string | null;
686
- variables?: Record<string, string> | null;
687
- error?: string;
688
- createdAt: string;
689
- }
690
- interface LiveTestExecutionPayload {
691
- testExecutionId: string;
692
- testIndex: number;
693
- testId: string;
694
- testName: string;
695
- }
696
- interface LiveTestStepPayload extends LiveTestExecutionPayload {
697
- stepIndex: number;
698
- stepInstruction: string;
699
- }
700
- interface LiveTestResultPayload {
701
- status: 'passed' | 'failed' | 'cancelled';
702
- duration: number;
703
- error?: string;
704
- setupHookExecutions: LiveHookPayload[];
705
- stepResults: LiveStepResultPayload[];
706
- teardownHookExecutions: LiveHookPayload[];
707
- }
708
- type ServerMessage = {
709
- type: 'session-ready';
710
- sessionId: string;
711
- platform: string;
712
- interactive: boolean;
713
- error?: string | null;
714
- } | {
715
- type: 'hook-start';
716
- hook: LiveHookPayload;
717
- } | {
718
- type: 'hook-complete';
719
- hook: LiveHookPayload;
720
- } | {
721
- type: 'step-phase';
722
- phase: string;
723
- data?: unknown;
724
- } | {
725
- type: 'step-complete';
726
- result: LiveStepResultPayload;
727
- } | {
728
- type: 'step-cancelled';
729
- } | {
730
- type: 'step-error';
731
- error: string;
732
- } | {
733
- type: 'test-start';
734
- test: LiveTestExecutionPayload;
735
- } | {
736
- type: 'test-step-start';
737
- step: LiveTestStepPayload;
738
- } | {
739
- type: 'test-step-phase';
740
- step: LiveTestStepPayload;
741
- phase: string;
742
- data?: unknown;
743
- } | {
744
- type: 'test-step-complete';
745
- step: LiveTestStepPayload;
746
- result: LiveStepResultPayload;
747
- } | {
748
- type: 'test-step-cancelled';
749
- step: LiveTestStepPayload;
750
- } | {
751
- type: 'test-step-error';
752
- step: LiveTestStepPayload;
753
- error: string;
754
- } | {
755
- type: 'test-complete';
756
- test: LiveTestExecutionPayload;
757
- result: LiveTestResultPayload;
758
- } | {
759
- type: 'test-error';
760
- test: LiveTestExecutionPayload;
761
- error: string;
762
- } | {
763
- type: 'screenshot';
764
- data: string;
765
- } | {
766
- type: 'session-state';
767
- state: SessionState;
768
- } | {
769
- type: 'session-terminated';
770
- } | {
771
- type: 'browser-disconnected';
772
- } | {
773
- type: 'error';
774
- message: string;
775
- } | {
776
- type: 'step-busy';
777
- currentStep: string;
778
- } | {
779
- type: 'navigate-complete';
780
- url: string | null;
781
- } | {
782
- type: 'device-logs';
783
- entries: Array<{
784
- level: string;
785
- message: string;
786
- timestamp: number;
787
- }>;
788
- } | {
789
- type: 'aria-tree';
790
- tree: string;
791
- };
792
- interface SessionState {
793
- sessionId: string;
794
- platform: 'web' | 'android' | 'ios';
795
- targetName?: string | null;
796
- status: 'idle' | 'executing' | 'disconnected';
797
- currentStep: string | null;
798
- currentUrl: string | null;
799
- stepsExecuted: number;
800
- createdAt: number;
801
- interactive: boolean;
802
- terminalError: string | null;
803
- }
804
- interface LiveSessionConfig {
805
- platform: 'web' | 'android' | 'ios';
806
- targetName?: string;
807
- llmConfig: LiveSessionLLMConfig;
808
- authFetch?: typeof globalThis.fetch;
809
- agentRules?: string;
810
- envVars?: Record<string, string>;
811
- secretStore?: SecretStore;
812
- secretRedactor?: SecretRedactor;
813
- setupHooks?: string[];
814
- teardownHooks?: string[];
815
- resolvedHooks?: Map<string, HookDefinition>;
816
- hookRegistryError?: string;
817
- url?: string;
818
- headless?: boolean;
819
- useDeviceName?: string;
820
- appState?: 'preserve' | 'reset';
821
- bundleId?: string;
822
- appPackage?: string;
823
- appActivity?: string;
824
- device?: {
825
- name: string;
826
- platformVersion?: string;
827
- appPath?: string;
828
- browserName?: string;
829
- appPackage?: string;
830
- appActivity?: string;
831
- bundleId?: string;
832
- udid?: string;
833
- avd?: string;
834
- appiumUrl?: string;
835
- };
836
- }
837
-
838
- interface LiveSessionDeps {
839
- appiumManager?: AppiumManager;
840
- configManager?: ConfigManager;
841
- configPath?: string;
842
- }
843
- interface LiveStepExecutionResult extends StepResult {
844
- executionLogs?: LiveExecutionLog[];
845
- subActionsData?: LiveSubActionData[];
846
- }
847
- declare class LiveSession {
848
- private deps;
849
- readonly sessionId: string;
850
- status: 'idle' | 'executing' | 'disconnected' | 'terminated';
851
- private abortController;
852
- stepsExecuted: number;
853
- createdAt: number;
854
- private adapter;
855
- private planner;
856
- private verifier;
857
- private model;
858
- private variableStore;
859
- private previousSteps;
860
- private currentStep;
861
- private platform;
862
- private targetName;
863
- private currentUrl;
864
- private executing;
865
- private idleTimer;
866
- private _modelName;
867
- private screenshotSize;
868
- private effectiveResolution;
869
- private readyForInteraction;
870
- private terminalError;
871
- private setupHooks;
872
- private teardownHooks;
873
- private resolvedHooks;
874
- private hookRegistryError;
875
- private pendingMessages;
876
- private messageSink;
877
- private mobileAppiumLease;
878
- private secretStore;
879
- private secretRedactor;
880
- constructor(sessionId: string, deps?: LiveSessionDeps);
881
- get modelName(): string;
882
- attachMessageSink(sink: ((message: ServerMessage) => void) | null): void;
883
- private dispatch;
884
- private redact;
885
- private resolveSecrets;
886
- private emitHookStart;
887
- private emitHookComplete;
888
- private emitTestStepStart;
889
- private emitTestStepPhase;
890
- private emitTestStepComplete;
891
- private emitTestStepError;
892
- private getHookEnvVars;
893
- private runLifecycleHooks;
894
- executeHookCommand(phase: 'setup' | 'teardown', hookId: string): Promise<LiveExecutionLog>;
895
- private releaseMobileAppiumLease;
896
- private legacyMobilePlatformConfig;
897
- private resolveMobilePlatformConfig;
898
- private setupMobileAdapter;
899
- initialize(config: LiveSessionConfig): Promise<void>;
900
- private resolveStepInstruction;
901
- private buildPreparationFailureResult;
902
- private executeStepInternal;
903
- executeStepCommand(stepInstruction: string, stepIndex?: number, onPhase?: (event: StepPhaseEvent) => void, draft?: LiveDraftMetadata): Promise<LiveStepExecutionResult>;
904
- executeTestCommand(testExecutionId: string, testDraft: {
905
- testIndex: number;
906
- testId: string;
907
- testName: string;
908
- testContext?: string;
909
- steps: string[];
910
- setup: string[];
911
- teardown: string[];
912
- }, onPhase?: (event: StepPhaseEvent) => void): Promise<LiveTestResultPayload>;
913
- private runLifecycleHooksCapturing;
914
- captureWebAuthState(name: string, options?: {
915
- replace?: boolean;
916
- }): Promise<AuthStateMetadata>;
917
- cancelStep(): void;
918
- navigate(url: string): Promise<string | null>;
919
- refreshPage(): Promise<string | null>;
920
- goBack(): Promise<string | null>;
921
- goForward(): Promise<string | null>;
922
- drainDeviceLogs(): Promise<Array<{
923
- level: string;
924
- message: string;
925
- timestamp: number;
926
- }>>;
927
- getState(): SessionState;
928
- getScreenshot(): Promise<Buffer | undefined>;
929
- getAriaTree(): Promise<string | null>;
930
- startIdleTimer(onExpire: () => void): void;
931
- clearIdleTimer(): void;
932
- cleanup(): Promise<void>;
933
- }
934
-
935
- interface SessionManagerDeps {
936
- appiumManager?: AppiumManager;
937
- configManager?: ConfigManager;
938
- configPath?: string;
939
- }
940
- declare class SessionManager {
941
- private deps;
942
- private sessions;
943
- private counters;
944
- constructor(deps?: SessionManagerDeps);
945
- createSession(config: LiveSessionConfig, entity?: EntityRef): Promise<{
946
- sessionId: string;
947
- sessionNumber: number | null;
948
- }>;
949
- getSession(sessionId: string): LiveSession | undefined;
950
- listSessions(): SessionState[];
951
- terminateSession(sessionId: string): Promise<boolean>;
952
- cleanupAll(): Promise<void>;
953
- getCounter(entity: EntityRef): number;
954
- get size(): number;
955
- }
956
-
957
- interface ExecuteOptions {
958
- runId: string;
959
- args: string[];
960
- source: string;
961
- attributes?: RunAttributes;
962
- timeout?: number;
963
- maxRetries?: number;
964
- env?: Record<string, string>;
965
- }
966
- interface ExecutionBackend extends EventEmitter {
967
- execute(opts: ExecuteOptions): void;
968
- kill(runId: string): boolean;
969
- killAll(): void;
970
- getActiveExecutions(): {
971
- runId: string;
972
- status: string;
973
- startedAt: string;
974
- duration: number;
975
- }[];
976
- }
977
-
978
- interface LiveExecutionEvent {
979
- id: number;
980
- type: string;
981
- [key: string]: unknown;
982
- }
983
- interface TestRunHandle {
984
- runId: string;
985
- process: ChildProcess;
986
- status: 'running' | 'completed' | 'failed' | 'cancelled' | 'timeout';
987
- output: string[];
988
- startedAt: Date;
989
- lastEventAt: number;
990
- completionReason?: string;
991
- }
992
- declare class TestRunner extends EventEmitter implements ExecutionBackend {
993
- private cliBin;
994
- private defaultTimeout;
995
- private handles;
996
- private eventBuffers;
997
- private eventCounters;
998
- private onProcessClose?;
999
- private heartbeatTimer;
1000
- private heartbeatIntervalMs;
1001
- private staleThresholdMs;
1002
- constructor(opts: {
1003
- cliBin: string;
1004
- defaultTimeout?: number;
1005
- onProcessClose?: (runId: string, status: 'completed' | 'failed' | 'cancelled' | 'timeout') => void;
1006
- heartbeatIntervalMs?: number;
1007
- staleThresholdMs?: number;
1008
- });
1009
- static resolveCliBin(): string;
1010
- execute(opts: ExecuteOptions): void;
1011
- getBufferedEvents(runId: string): LiveExecutionEvent[];
1012
- getHandle(runId: string): TestRunHandle | undefined;
1013
- getActiveExecutions(): {
1014
- runId: string;
1015
- status: string;
1016
- startedAt: string;
1017
- duration: number;
1018
- testName?: string;
1019
- }[];
1020
- kill(runId: string): boolean;
1021
- killAll(): void;
1022
- private startHeartbeatChecker;
1023
- private pushEvent;
1024
- private signalHandle;
1025
- }
1026
-
1027
- interface EnqueueOptions {
1028
- name: string;
1029
- filePath?: string;
1030
- kind?: RunArtifactKind;
1031
- attributes?: RunAttributes;
1032
- priority?: number;
1033
- platform?: string;
1034
- testFileContent?: string;
1035
- modelName?: string;
1036
- llmProvider?: string;
1037
- metadata?: Record<string, unknown>;
1038
- parallel?: boolean;
1039
- }
1040
- declare class JobQueue extends EventEmitter {
1041
- private db;
1042
- private pollInterval;
1043
- private isProcessing;
1044
- private concurrency;
1045
- private activeCount;
1046
- private activePlatforms;
1047
- private activeRuns;
1048
- constructor(opts: {
1049
- db: DashboardDatabase;
1050
- concurrency?: number;
1051
- });
1052
- start(intervalMs?: number): void;
1053
- stop(): void;
1054
- enqueue(opts: EnqueueOptions): string;
1055
- processNext(): void;
1056
- onSlotFreed(runId: string): void;
1057
- getActiveCount(): number;
1058
- getConcurrency(): number;
1059
- cancel(runId: string): boolean;
1060
- private cancelChildRuns;
1061
- private findNextEligible;
1062
- }
1063
-
1064
- interface TestFileInfo {
1065
- path: string;
1066
- name: string;
1067
- testId: string | null;
1068
- targetName: string | null;
1069
- platform: string | null;
1070
- modified: string;
1071
- }
1072
- interface TestValidationError {
1073
- message: string;
1074
- line?: number;
1075
- column?: number;
1076
- suggestion?: string;
1077
- }
1078
- interface TestValidationResult {
1079
- valid: boolean;
1080
- errors: TestValidationError[];
1081
- }
1082
- declare class TestFileManager {
1083
- private readonly workspace;
1084
- constructor(workspace: ResolvedWorkspacePaths);
1085
- list(): Promise<TestFileInfo[]>;
1086
- read(relativePath: string): Promise<string>;
1087
- findByTestId(testId: string): Promise<{
1088
- path: string;
1089
- content: string;
1090
- } | null>;
1091
- write(relativePath: string, content: string): Promise<void>;
1092
- delete(relativePath: string): Promise<void>;
1093
- validate(content: string): Promise<TestValidationResult>;
1094
- private resolveTarget;
1095
- }
1096
-
1097
- interface SuiteFileInfo {
1098
- path: string;
1099
- suiteId: string | null;
1100
- name: string;
1101
- testCount: number;
1102
- modified: string;
1103
- platform: string | null;
1104
- }
1105
- interface SuiteValidationResult {
1106
- valid: boolean;
1107
- errors: {
1108
- message: string;
1109
- line?: number;
1110
- column?: number;
1111
- suggestion?: string;
1112
- }[];
1113
- missingTests?: Array<{
1114
- index: number;
1115
- test: string;
1116
- id: string;
1117
- }>;
1118
- }
1119
- declare class SuiteFileManager {
1120
- private readonly workspace;
1121
- private testFileManager;
1122
- constructor(workspace: ResolvedWorkspacePaths, testFileManager?: TestFileManager);
1123
- list(): Promise<SuiteFileInfo[]>;
1124
- findBySuiteId(suiteId: string): Promise<{
1125
- path: string;
1126
- content: string;
1127
- } | null>;
1128
- resolvePath(filePath: string, requireExisting?: boolean): Promise<{
1129
- storagePath: string;
1130
- executionPath: string;
1131
- }>;
1132
- read(relativePath: string): Promise<string>;
1133
- write(relativePath: string, content: string): Promise<void>;
1134
- delete(relativePath: string): Promise<void>;
1135
- validate(content: string): Promise<SuiteValidationResult>;
1136
- private resolveTarget;
1137
- }
1138
-
1139
- type DashboardRuntimeLLMConfig = Pick<ModelConfig, 'provider' | 'model' | 'apiKey' | 'authToken' | 'baseURL' | 'providerHeaders'> & {
1140
- screenshotSize?: number;
1141
- effectiveResolution?: number;
1142
- modelAdapter?: 'openai-responses' | 'anthropic-messages';
1143
- };
1144
- interface RouterDeps {
1145
- db: DashboardDatabase;
1146
- artifactsDir?: string;
1147
- workspacePaths?: ResolvedWorkspacePaths;
1148
- testRunner?: TestRunner;
1149
- jobQueue?: JobQueue;
1150
- testFileManager?: TestFileManager;
1151
- suiteFileManager?: SuiteFileManager;
1152
- configManager?: ConfigManager;
1153
- configPath?: string;
1154
- llmConfig?: DashboardRuntimeLLMConfig;
1155
- authFetch?: typeof globalThis.fetch;
1156
- sessionManager?: SessionManager;
1157
- analyticsBridge?: {
1158
- buildAnalyticsEvent: typeof buildAnalyticsEvent;
1159
- captureAnalytics: typeof captureAnalytics;
1160
- resolveAnalyticsStandardProperties: typeof resolveAnalyticsStandardProperties;
1161
- };
1162
- }
1163
- declare function createRouter(deps: RouterDeps): (req: IncomingMessage, res: ServerResponse) => void;
1164
- declare function createRouter(db: DashboardDatabase, artifactsDir?: string): (req: IncomingMessage, res: ServerResponse) => void;
1165
-
1166
- declare function readJsonBody<T>(req: IncomingMessage, maxBytes?: number): Promise<T>;
1167
-
1168
- export { AppiumManager as A, ConfigManager as C, DashboardDatabase as D, type LiveExecutionEvent as L, type RunRow as R, type StepRow as S, type TestFileInfo as T, TestFileManager as a, type TestRunHandle as b, TestRunner as c, type TestValidationError as d, type TestValidationResult as e, createRouter as f, readJsonBody as r, startServer as s };