fix(core): transcript cannot retry (#15476)

#### PR Dependency Tree


* **PR #15476** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

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

## Summary by CodeRabbit

- **Bug Fixes**
- Improved connectivity for AI services configured with a global
location while preserving support for regional locations.
- Failed audio transcription jobs can now be restarted without
recreating the job.
- Preserved existing behavior for transcription jobs that are still
waiting or already in other non-retryable states.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-08-13 02:42:34 +08:00
committed by GitHub
parent 9693593d05
commit 18977f2048
2 changed files with 46 additions and 5 deletions
@@ -248,9 +248,12 @@ fn managed_endpoint(profile: &CopilotManagedProfileConfig) -> RuntimeResult<Back
} else {
"anthropic"
};
format!(
"https://{location}-aiplatform.googleapis.com/v1/projects/{project}/locations/{location}/publishers/{publisher}"
)
let host = if location == "global" {
"aiplatform.googleapis.com".to_string()
} else {
format!("{location}-aiplatform.googleapis.com")
};
format!("https://{host}/v1/projects/{project}/locations/{location}/publishers/{publisher}")
}
"cloudflareWorkersAi" => format!(
"https://api.cloudflare.com/client/v4/accounts/{}/ai",
@@ -311,3 +314,41 @@ pub(super) fn required_config_text<'a>(
.filter(|value| !value.trim().is_empty())
.ok_or_else(|| RuntimeError::invalid_state(format!("managed copilot profile requires {field}")))
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::{BackendEndpoint, CopilotManagedProfileConfig, managed_endpoint};
fn vertex_profile(location: &str) -> CopilotManagedProfileConfig {
CopilotManagedProfileConfig {
id: "vertex".to_string(),
provider: "geminiVertex".to_string(),
enabled: true,
models: vec!["gemini-3.6-flash".to_string()],
config: json!({ "project": "affine-us", "location": location }),
}
}
#[test]
fn managed_vertex_endpoint_uses_global_host() {
assert_eq!(
managed_endpoint(&vertex_profile("global")).unwrap(),
BackendEndpoint::Custom(
"https://aiplatform.googleapis.com/v1/projects/affine-us/locations/global/publishers/google".to_string()
)
);
}
#[test]
fn managed_vertex_endpoint_uses_regional_host() {
assert_eq!(
managed_endpoint(&vertex_profile("us-central1")).unwrap(),
BackendEndpoint::Custom(
"https://us-central1-aiplatform.googleapis.com/v1/projects/affine-us/locations/us-central1/publishers/google"
.to_string()
)
);
}
}
@@ -169,8 +169,8 @@ export class AudioAttachmentBlock extends Entity<AttachmentBlockModel> {
readonly transcribe = async () => {
try {
// if job is already running, we should not start it again
if (this.transcriptionJob.status$.value.status !== 'waiting-for-job') {
const initialStatus = this.transcriptionJob.status$.value.status;
if (initialStatus !== 'waiting-for-job' && initialStatus !== 'failed') {
return;
}
const status = await this.transcriptionJob.start();