fix(files): принадлежность файла задаче — дозаполнение task_id/field_id + MCP-проверка с сериализацией значений

Живой тест показал: 77 файлов отслеживаются, но get_task_file отвечал «не
относится к задаче» — старые backfill-строки без task_id/field_id (ON CONFLICT
DO NOTHING их не обновлял), а проверка по file-полям искала ключ только в
строковых значениях (file-поля хранятся объектом/массивом).
- MCP get_task_file: поиск ключа в JSON.stringify(value) для нестроковых значений;
- trackFileOnDemand: у существующих строк без task_id дозаполняет taskId/fieldId;
- startup-backfill: UPDATE task_id/field_id из task_field_values и task_messages
  для строк с task_id IS NULL.
This commit is contained in:
2026-09-29 10:50:34 +03:00
parent 102f5410b1
commit 0b4324c23d
3 changed files with 68 additions and 3 deletions

View File

@@ -78,13 +78,27 @@ interface FileReferenceRow {
*/
export async function trackFileOnDemand(fileKey: string): Promise<boolean> {
const existing = await db
.select({ id: fileUploads.id })
.select()
.from(fileUploads)
.where(eq(fileUploads.fileKey, fileKey))
.limit(1);
if (existing.length > 0) return true;
try {
// Уже отслеживается, но без привязки к задаче (старые backfill-строки) —
// пытаемся дозаполнить taskId/fieldId из ссылок
if (existing.length > 0) {
const row = existing[0];
if (row.taskId == null) {
const ref = await findFileReference(fileKey);
if (ref?.taskId != null) {
await db.update(fileUploads)
.set({ taskId: ref.taskId, fieldId: row.fieldId ?? ref.fieldId })
.where(eq(fileUploads.id, row.id));
}
}
return true;
}
const ref = await findFileReference(fileKey);
// uploadedBy NOT NULL в схеме — без владельца записать не сможем
if (!ref || ref.uploadedBy == null) return false;