Merge remote-tracking branch 'origin/v0.14.0rc' into feature/v0.14.0rc-1768981415660-tt2v

# Conflicts:
#	apps/ui/src/components/views/project-settings-view/config/navigation.ts
#	apps/ui/src/components/views/project-settings-view/hooks/use-project-settings-view.ts
This commit is contained in:
Shirone
2026-01-21 17:46:22 +01:00
61 changed files with 4752 additions and 213 deletions

View File

@@ -562,6 +562,9 @@ type EventType =
| 'dev-server:started'
| 'dev-server:output'
| 'dev-server:stopped'
| 'test-runner:started'
| 'test-runner:output'
| 'test-runner:completed'
| 'notification:created';
/**
@@ -593,6 +596,44 @@ export type DevServerLogEvent =
| { type: 'dev-server:output'; payload: DevServerOutputEvent }
| { type: 'dev-server:stopped'; payload: DevServerStoppedEvent };
/**
* Test runner event payloads for WebSocket streaming
*/
export type TestRunStatus = 'pending' | 'running' | 'passed' | 'failed' | 'cancelled' | 'error';
export interface TestRunnerStartedEvent {
sessionId: string;
worktreePath: string;
/** The test command being run (from project settings) */
command: string;
testFile?: string;
timestamp: string;
}
export interface TestRunnerOutputEvent {
sessionId: string;
worktreePath: string;
content: string;
timestamp: string;
}
export interface TestRunnerCompletedEvent {
sessionId: string;
worktreePath: string;
/** The test command that was run */
command: string;
status: TestRunStatus;
testFile?: string;
exitCode: number | null;
duration: number;
timestamp: string;
}
export type TestRunnerEvent =
| { type: 'test-runner:started'; payload: TestRunnerStartedEvent }
| { type: 'test-runner:output'; payload: TestRunnerOutputEvent }
| { type: 'test-runner:completed'; payload: TestRunnerCompletedEvent };
/**
* Response type for fetching dev server logs
*/
@@ -608,6 +649,26 @@ export interface DevServerLogsResponse {
error?: string;
}
/**
* Response type for fetching test logs
*/
export interface TestLogsResponse {
success: boolean;
result?: {
sessionId: string;
worktreePath: string;
/** The test command that was/is being run */
command: string;
status: TestRunStatus;
testFile?: string;
logs: string;
startedAt: string;
finishedAt: string | null;
exitCode: number | null;
};
error?: string;
}
type EventCallback = (payload: unknown) => void;
interface EnhancePromptResult {
@@ -2001,6 +2062,32 @@ export class HttpApiClient implements ElectronAPI {
unsub3();
};
},
// Test runner methods
startTests: (worktreePath: string, options?: { projectPath?: string; testFile?: string }) =>
this.post('/api/worktree/start-tests', { worktreePath, ...options }),
stopTests: (sessionId: string) => this.post('/api/worktree/stop-tests', { sessionId }),
getTestLogs: (worktreePath?: string, sessionId?: string): Promise<TestLogsResponse> => {
const params = new URLSearchParams();
if (worktreePath) params.append('worktreePath', worktreePath);
if (sessionId) params.append('sessionId', sessionId);
return this.get(`/api/worktree/test-logs?${params.toString()}`);
},
onTestRunnerEvent: (callback: (event: TestRunnerEvent) => void) => {
const unsub1 = this.subscribeToEvent('test-runner:started', (payload) =>
callback({ type: 'test-runner:started', payload: payload as TestRunnerStartedEvent })
);
const unsub2 = this.subscribeToEvent('test-runner:output', (payload) =>
callback({ type: 'test-runner:output', payload: payload as TestRunnerOutputEvent })
);
const unsub3 = this.subscribeToEvent('test-runner:completed', (payload) =>
callback({ type: 'test-runner:completed', payload: payload as TestRunnerCompletedEvent })
);
return () => {
unsub1();
unsub2();
unsub3();
};
},
};
// Git API
@@ -2362,6 +2449,7 @@ export class HttpApiClient implements ElectronAPI {
defaultDeleteBranchWithWorktree?: boolean;
autoDismissInitScriptIndicator?: boolean;
lastSelectedSessionId?: string;
testCommand?: string;
};
error?: string;
}> => this.post('/api/settings/project', { projectPath }),