feat(server): realtime handle & migration (#15487)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Retry failed Copilot transcription tasks in real time.
  * Retried tasks resume processing and report updated status.
* Managed Copilot provider models can be omitted to use provider
defaults.

* **Bug Fixes**
* Improved handling of incomplete BYOK profiles, including safe
replacement of legacy records.
  * Duplicate profile creation now returns a clear validation error.
* Improved transcript processing reliability by preventing duplicate or
stale dispatches.

* **Migration**
* Consolidated legacy managed-provider settings while preserving
existing profiles and defaults.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-08-16 08:04:19 +08:00
committed by GitHub
parent ff1e3d9c94
commit 06b3d020fa
27 changed files with 1118 additions and 175 deletions
@@ -11,12 +11,14 @@ import {
} from '../../../core/realtime';
import { assertCopilotEnabled } from '../availability';
import { CopilotTranscriptionReader } from './reader';
import { CopilotTranscriptionRetryService } from './retry';
@Injectable()
export class CopilotTranscriptRealtimeProvider implements OnModuleInit {
constructor(
private readonly ac: PermissionAccess,
private readonly transcript: CopilotTranscriptionReader,
private readonly retry: CopilotTranscriptionRetryService,
private readonly registry: RealtimeRegistry,
private readonly config: Config
) {}
@@ -34,6 +36,24 @@ export class CopilotTranscriptRealtimeProvider implements OnModuleInit {
taskId: z.string(),
});
this.registry.registerRequest({
name: 'copilot.transcript.task.retry',
input: z.object({
workspaceId: z.string(),
taskId: z.string(),
}),
handle: async (user, input) => {
await this.assertCopilot(user.id, input.workspaceId);
return {
task: await this.retry.retryTask(
user.id,
input.workspaceId,
input.taskId
),
};
},
});
registerRealtimeLiveQuery(this.registry, {
request: {
name: 'copilot.transcript.task.get',