Desktop: adopt server recording by title for pre-mapping files; refresh stale reports missing a summary

This commit is contained in:
avi 2026-09-14 09:53:40 -05:00
commit 0fa558b1a7

View file

@ -718,10 +718,33 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
) )
_detail.value = d _detail.value = d
go(Screen.DETAIL) go(Screen.DETAIL)
pollJob = scope.launch {
// Files that predate remote-id mapping have no sidecar: adopt
// the server recording by exact title match so Re-summarize
// appears and finished AI outputs become reachable.
var remoteId = d.remoteId
if (remoteId == null) {
remoteId = adoptServerRecording(d)
if (_detail.value?.file != file) return@launch
}
if (remoteId == null) return@launch
// Report written before a summary existed (or lost a race):
// pull finished outputs so the detail view isn't stale.
val report = d.reportText
if (d.transcript == null && !report.isNullOrBlank() && !report.contains("## Summary")) {
val t = runCatching { parseTranscript(provider.fetchTranscript(remoteId)) }
.getOrNull()
val s = runCatching { parseSummary(provider.fetchSummary(remoteId)) }
.getOrNull()
if (s != null) {
d.transcript = t ?: d.transcript
d.summary = s
saveReport(d)
if (_detail.value?.file == file) _detail.value = d.copy()
}
}
// If the file is mid-pipeline (pump running, or reprocess started // If the file is mid-pipeline (pump running, or reprocess started
// elsewhere), show live stage/progress instead of a stale report. // elsewhere), show live stage/progress instead of a stale report.
val remoteId = d.remoteId ?: return
pollJob = scope.launch {
while (true) { while (true) {
val jobs = runCatching { parseJobs(provider.fetchJobs(remoteId)) } val jobs = runCatching { parseJobs(provider.fetchJobs(remoteId)) }
.getOrNull().orEmpty() .getOrNull().orEmpty()
@ -736,6 +759,32 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
} }
} }
/** Find the server recording matching [d]'s file by title and persist
* the mapping. Returns the recording id, or null when no server-side
* row carries this exact title. */
private suspend fun adoptServerRecording(d: DetailUi): String? {
val wanted = d.file.nameWithoutExtension
return runCatching {
var cursor: String? = null
var adopted: String? = null
var scanned = 0
do {
val page = provider.list(cursor)
val matches = page.items.filter { it.title == wanted }
// Only adopt when the title is unambiguous server-side.
if (matches.size == 1) adopted = matches.first().ref.key
if (matches.size > 1) return@runCatching null
cursor = page.nextCursor
scanned += page.items.size
} while (cursor != null && scanned < 400)
adopted?.let {
saveMapping(d.file, RemoteMapping(it, title = wanted))
d.remoteId = it
}
adopted
}.getOrNull()
}
fun setOverride(model: String?) { fun setOverride(model: String?) {
_detail.value?.let { it.overrideModel = model; _detail.value = it.copy() } _detail.value?.let { it.overrideModel = model; _detail.value = it.copy() }
} }