@musnows/scriverse 0.5.7 → 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.js +350 -67
- package/dist/ai.js.map +1 -1
- package/dist/app.js +51 -35
- package/dist/app.js.map +1 -1
- package/dist/cli-core.js +161 -20
- package/dist/cli-core.js.map +1 -1
- package/dist/database.js +72 -0
- package/dist/database.js.map +1 -1
- package/dist/hybrid-search.js +106 -0
- package/dist/hybrid-search.js.map +1 -0
- package/dist/public/app.js +252 -57
- package/dist/public/display-labels.js +13 -1
- package/dist/public/global-search.d.ts +6 -5
- package/dist/public/global-search.js +44 -3
- package/dist/public/index.html +21 -8
- package/dist/public/race-hierarchy.js +0 -35
- package/dist/public/styles.css +27 -6
- package/dist/relationship-search.js +21 -2
- package/dist/relationship-search.js.map +1 -1
- package/dist/store.js +167 -6
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +27 -1
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/store.js
CHANGED
|
@@ -660,6 +660,12 @@ export class Store {
|
|
|
660
660
|
autoRunEnabled: Number(row?.auto_run_enabled ?? 0) === 1,
|
|
661
661
|
autoRunConcurrency: Math.min(8, Math.max(1, Number(row?.auto_run_concurrency ?? 2) || 2)),
|
|
662
662
|
autoRunBatchLimit: Math.min(200, Math.max(1, Number(row?.auto_run_batch_limit ?? 20) || 20)),
|
|
663
|
+
autoRunDailyTaskLimit: Math.min(10_000, Math.max(0, Number(row?.auto_run_daily_task_limit ?? 0) || 0)),
|
|
664
|
+
autoRunFailureThreshold: Math.min(10, Math.max(1, Number(row?.auto_run_failure_threshold ?? 3) || 3)),
|
|
665
|
+
autoRunPaused: Number(row?.auto_run_paused ?? 0) === 1,
|
|
666
|
+
autoRunPauseReason: String(row?.auto_run_pause_reason ?? ""),
|
|
667
|
+
autoRunResumeAt: row?.auto_run_resume_at === null || row?.auto_run_resume_at === undefined ? null : String(row.auto_run_resume_at),
|
|
668
|
+
autoRunConsecutiveFailures: Math.max(0, Number(row?.auto_run_consecutive_failures ?? 0) || 0),
|
|
663
669
|
bookSummaryContextPercent: Math.min(90, Math.max(1, Number(row?.book_summary_context_percent ?? 50) || 50)),
|
|
664
670
|
contextCompactThreshold: Math.min(90, Math.max(50, Number(row?.context_compact_threshold ?? 85) || 85)),
|
|
665
671
|
agentTools: json(String(row?.agent_tools_json ?? '["story_index","read_chapters","search_story_entities","grep","read_character_sections"]'), ["story_index", "read_chapters", "search_story_entities", "grep", "read_character_sections"])
|
|
@@ -676,32 +682,92 @@ export class Store {
|
|
|
676
682
|
const nextEnabled = input.autoRunEnabled ?? Boolean(current.autoRunEnabled);
|
|
677
683
|
const nextConcurrency = input.autoRunConcurrency ?? Number(current.autoRunConcurrency);
|
|
678
684
|
const nextBatchLimit = input.autoRunBatchLimit ?? Number(current.autoRunBatchLimit);
|
|
685
|
+
const nextDailyTaskLimit = input.autoRunDailyTaskLimit ?? Number(current.autoRunDailyTaskLimit);
|
|
686
|
+
const nextFailureThreshold = input.autoRunFailureThreshold ?? Number(current.autoRunFailureThreshold);
|
|
679
687
|
const nextBookSummaryContextPercent = input.bookSummaryContextPercent ?? Number(current.bookSummaryContextPercent);
|
|
680
688
|
const nextContextCompactThreshold = input.contextCompactThreshold ?? Number(current.contextCompactThreshold);
|
|
681
689
|
const nextAgentTools = input.agentTools ?? current.agentTools;
|
|
682
690
|
this.db.run(`INSERT INTO work_ai_settings (
|
|
683
|
-
work_id, system_prompt, auto_run_enabled, auto_run_concurrency, auto_run_batch_limit,
|
|
684
|
-
|
|
691
|
+
work_id, system_prompt, auto_run_enabled, auto_run_concurrency, auto_run_batch_limit,
|
|
692
|
+
auto_run_daily_task_limit, auto_run_failure_threshold, auto_run_paused, auto_run_pause_reason,
|
|
693
|
+
auto_run_resume_at, auto_run_consecutive_failures, book_summary_context_percent,
|
|
694
|
+
context_compact_threshold, agent_tools_json, updated_at
|
|
695
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
685
696
|
ON CONFLICT(work_id) DO UPDATE SET
|
|
686
697
|
system_prompt = excluded.system_prompt,
|
|
687
698
|
auto_run_enabled = excluded.auto_run_enabled,
|
|
688
699
|
auto_run_concurrency = excluded.auto_run_concurrency,
|
|
689
700
|
auto_run_batch_limit = excluded.auto_run_batch_limit,
|
|
701
|
+
auto_run_daily_task_limit = excluded.auto_run_daily_task_limit,
|
|
702
|
+
auto_run_failure_threshold = excluded.auto_run_failure_threshold,
|
|
703
|
+
auto_run_paused = excluded.auto_run_paused,
|
|
704
|
+
auto_run_pause_reason = excluded.auto_run_pause_reason,
|
|
705
|
+
auto_run_resume_at = excluded.auto_run_resume_at,
|
|
706
|
+
auto_run_consecutive_failures = excluded.auto_run_consecutive_failures,
|
|
690
707
|
book_summary_context_percent = excluded.book_summary_context_percent,
|
|
691
708
|
context_compact_threshold = excluded.context_compact_threshold,
|
|
692
709
|
agent_tools_json = excluded.agent_tools_json,
|
|
693
|
-
updated_at = excluded.updated_at`, workId, nextPrompt, nextEnabled ? 1 : 0, Math.min(8, Math.max(1, nextConcurrency)), Math.min(200, Math.max(1, nextBatchLimit)), Math.min(90, Math.max(1, nextBookSummaryContextPercent)), Math.min(90, Math.max(50, nextContextCompactThreshold)), JSON.stringify(nextAgentTools), timestamp);
|
|
710
|
+
updated_at = excluded.updated_at`, workId, nextPrompt, nextEnabled ? 1 : 0, Math.min(8, Math.max(1, nextConcurrency)), Math.min(200, Math.max(1, nextBatchLimit)), Math.min(10_000, Math.max(0, nextDailyTaskLimit)), Math.min(10, Math.max(1, nextFailureThreshold)), current.autoRunPaused ? 1 : 0, String(current.autoRunPauseReason ?? ""), current.autoRunResumeAt === null ? null : String(current.autoRunResumeAt), Math.max(0, Number(current.autoRunConsecutiveFailures) || 0), Math.min(90, Math.max(1, nextBookSummaryContextPercent)), Math.min(90, Math.max(50, nextContextCompactThreshold)), JSON.stringify(nextAgentTools), timestamp);
|
|
694
711
|
this.audit(workId, "work.ai-settings.updated", "work-ai-settings", workId, {
|
|
695
712
|
systemPromptChanged: input.systemPrompt !== undefined,
|
|
696
713
|
autoRunEnabled: nextEnabled,
|
|
697
714
|
autoRunConcurrency: Math.min(8, Math.max(1, nextConcurrency)),
|
|
698
715
|
autoRunBatchLimit: Math.min(200, Math.max(1, nextBatchLimit)),
|
|
716
|
+
autoRunDailyTaskLimit: Math.min(10_000, Math.max(0, nextDailyTaskLimit)),
|
|
717
|
+
autoRunFailureThreshold: Math.min(10, Math.max(1, nextFailureThreshold)),
|
|
699
718
|
bookSummaryContextPercent: Math.min(90, Math.max(1, nextBookSummaryContextPercent)),
|
|
700
719
|
contextCompactThreshold: Math.min(90, Math.max(50, nextContextCompactThreshold)),
|
|
701
720
|
agentTools: nextAgentTools
|
|
702
721
|
});
|
|
703
722
|
return this.getWorkAiSettings(workId);
|
|
704
723
|
}
|
|
724
|
+
clearAutoRunPause(workId) {
|
|
725
|
+
this.getWork(workId);
|
|
726
|
+
const current = this.getWorkAiSettings(workId);
|
|
727
|
+
this.db.run(`UPDATE work_ai_settings
|
|
728
|
+
SET auto_run_paused = 0, auto_run_pause_reason = '', auto_run_resume_at = NULL,
|
|
729
|
+
auto_run_consecutive_failures = 0, updated_at = ?
|
|
730
|
+
WHERE work_id = ?`, now(), workId);
|
|
731
|
+
if (current.autoRunPaused) {
|
|
732
|
+
this.audit(workId, "task.auto-run.resumed", "work-ai-settings", workId, {
|
|
733
|
+
previousReason: current.autoRunPauseReason
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
return this.getWorkAiSettings(workId);
|
|
737
|
+
}
|
|
738
|
+
pauseAutoRun(workId, reason, resumeAt = null) {
|
|
739
|
+
this.getWork(workId);
|
|
740
|
+
this.db.run(`UPDATE work_ai_settings
|
|
741
|
+
SET auto_run_paused = 1, auto_run_pause_reason = ?, auto_run_resume_at = ?, updated_at = ?
|
|
742
|
+
WHERE work_id = ?`, reason.slice(0, 500), resumeAt, now(), workId);
|
|
743
|
+
this.audit(workId, "task.auto-run.paused", "work-ai-settings", workId, { reason, resumeAt });
|
|
744
|
+
return this.getWorkAiSettings(workId);
|
|
745
|
+
}
|
|
746
|
+
recordAutoRunSuccess(workId) {
|
|
747
|
+
this.getWork(workId);
|
|
748
|
+
this.db.run("UPDATE work_ai_settings SET auto_run_consecutive_failures = 0, updated_at = ? WHERE work_id = ?", now(), workId);
|
|
749
|
+
return this.getWorkAiSettings(workId);
|
|
750
|
+
}
|
|
751
|
+
recordAutoRunFailure(workId, message, pauseImmediately = false) {
|
|
752
|
+
return this.db.transaction(() => {
|
|
753
|
+
const current = this.getWorkAiSettings(workId);
|
|
754
|
+
const consecutiveFailures = Number(current.autoRunConsecutiveFailures) + 1;
|
|
755
|
+
const shouldPause = pauseImmediately || consecutiveFailures >= Number(current.autoRunFailureThreshold);
|
|
756
|
+
this.db.run(`UPDATE work_ai_settings
|
|
757
|
+
SET auto_run_consecutive_failures = ?, auto_run_paused = ?,
|
|
758
|
+
auto_run_pause_reason = CASE WHEN ? = 1 THEN ? ELSE auto_run_pause_reason END,
|
|
759
|
+
auto_run_resume_at = CASE WHEN ? = 1 THEN NULL ELSE auto_run_resume_at END,
|
|
760
|
+
updated_at = ? WHERE work_id = ?`, consecutiveFailures, shouldPause ? 1 : 0, shouldPause ? 1 : 0, `连续任务失败,自动执行已暂停:${message}`.slice(0, 500), shouldPause ? 1 : 0, now(), workId);
|
|
761
|
+
if (shouldPause) {
|
|
762
|
+
this.audit(workId, "task.auto-run.paused", "work-ai-settings", workId, {
|
|
763
|
+
reason: "consecutive-failures",
|
|
764
|
+
consecutiveFailures,
|
|
765
|
+
message
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
return this.getWorkAiSettings(workId);
|
|
769
|
+
});
|
|
770
|
+
}
|
|
705
771
|
updateWork(workId, input, expectedVersionNo, source = "manual", sourceRef = null, changeNote = "") {
|
|
706
772
|
this.db.transaction(() => {
|
|
707
773
|
const current = this.getWork(workId);
|
|
@@ -1027,7 +1093,7 @@ export class Store {
|
|
|
1027
1093
|
throw new AppError(409, "VOLUME_NOT_EMPTY", "卷内仍有章节,需先移动或删除章节");
|
|
1028
1094
|
}
|
|
1029
1095
|
if (numberValue(counts ?? {}, "deleted_count") > 0) {
|
|
1030
|
-
throw new AppError(409, "VOLUME_HAS_DELETED_CHAPTERS", "
|
|
1096
|
+
throw new AppError(409, "VOLUME_HAS_DELETED_CHAPTERS", "分卷回收站中仍有章节,请先彻底删除或恢复并移动这些章节");
|
|
1031
1097
|
}
|
|
1032
1098
|
this.recordEntityVersion("volume", volumeId, "delete", null, "删除分卷");
|
|
1033
1099
|
this.db.run("DELETE FROM volumes WHERE id = ?", volumeId);
|
|
@@ -1620,6 +1686,35 @@ export class Store {
|
|
|
1620
1686
|
this.audit(String(chapter.workId), "chapter.deleted", "chapter", chapterId, { versionNo });
|
|
1621
1687
|
});
|
|
1622
1688
|
}
|
|
1689
|
+
permanentlyDeleteChapter(chapterId, expectedVersionNo) {
|
|
1690
|
+
const chapter = this.db.get("SELECT * FROM chapters WHERE id = ?", chapterId);
|
|
1691
|
+
if (!chapter)
|
|
1692
|
+
throw notFound("章节");
|
|
1693
|
+
if (!chapter.deleted_at)
|
|
1694
|
+
throw new AppError(409, "CHAPTER_NOT_IN_RECYCLE_BIN", "仅回收站中的章节可以彻底删除");
|
|
1695
|
+
this.assertExpectedRevision("chapter", chapterId, expectedVersionNo, "章节", numberValue(chapter, "version_no"));
|
|
1696
|
+
const workId = requiredString(chapter, "work_id");
|
|
1697
|
+
const timestamp = now();
|
|
1698
|
+
this.db.transaction(() => {
|
|
1699
|
+
const locked = this.db.get("SELECT * FROM chapters WHERE id = ?", chapterId);
|
|
1700
|
+
if (!locked)
|
|
1701
|
+
throw notFound("章节");
|
|
1702
|
+
if (!locked.deleted_at)
|
|
1703
|
+
throw new AppError(409, "CHAPTER_NOT_IN_RECYCLE_BIN", "仅回收站中的章节可以彻底删除");
|
|
1704
|
+
this.assertExpectedRevision("chapter", chapterId, expectedVersionNo, "章节", numberValue(locked, "version_no"));
|
|
1705
|
+
this.db.run("DELETE FROM chapter_versions WHERE chapter_id = ?", chapterId);
|
|
1706
|
+
this.db.run("DELETE FROM entity_versions WHERE entity_type = 'chapter-outline' AND entity_id = ?", chapterId);
|
|
1707
|
+
this.db.run("DELETE FROM attachment_references WHERE entity_type = 'chapter' AND entity_id = ?", chapterId);
|
|
1708
|
+
this.db.run("DELETE FROM chapters WHERE id = ?", chapterId);
|
|
1709
|
+
this.db.run("UPDATE works SET updated_at = ? WHERE id = ?", timestamp, workId);
|
|
1710
|
+
this.audit(workId, "chapter.purged", "chapter", chapterId, {
|
|
1711
|
+
title: requiredString(locked, "title"),
|
|
1712
|
+
volumeId: requiredString(locked, "volume_id"),
|
|
1713
|
+
versionNo: numberValue(locked, "version_no"),
|
|
1714
|
+
recoverable: false
|
|
1715
|
+
});
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1623
1718
|
insertChapter(workId, volumeId, title, content, sortOrder, source, sourceRef, chapterType = "正文") {
|
|
1624
1719
|
const chapterId = id("chapter");
|
|
1625
1720
|
const timestamp = now();
|
|
@@ -2179,6 +2274,19 @@ export class Store {
|
|
|
2179
2274
|
this.getWork(workId);
|
|
2180
2275
|
return this.db.all("SELECT * FROM races WHERE work_id = ? ORDER BY name", workId).map((row) => this.mapRace(row, includeMarkdown));
|
|
2181
2276
|
}
|
|
2277
|
+
listRacesByHierarchyScope(workId, scope, includeMarkdown = true) {
|
|
2278
|
+
this.getWork(workId);
|
|
2279
|
+
const hierarchyCondition = scope === "roots" ? "IS NULL" : "IS NOT NULL";
|
|
2280
|
+
return this.db.all(`SELECT race.*,
|
|
2281
|
+
(SELECT COUNT(*) FROM races child WHERE child.parent_race_id = race.id) AS child_count
|
|
2282
|
+
FROM races race
|
|
2283
|
+
WHERE race.work_id = ? AND race.parent_race_id ${hierarchyCondition}
|
|
2284
|
+
ORDER BY race.name`, workId).map((row) => this.mapRace(row, includeMarkdown));
|
|
2285
|
+
}
|
|
2286
|
+
countRaces(workId) {
|
|
2287
|
+
this.getWork(workId);
|
|
2288
|
+
return numberValue(this.db.get("SELECT COUNT(*) AS count FROM races WHERE work_id = ?", workId) ?? {}, "count");
|
|
2289
|
+
}
|
|
2182
2290
|
listRacesPage(workId, pagination, includeMarkdown = true) {
|
|
2183
2291
|
this.getWork(workId);
|
|
2184
2292
|
const page = paginationSql(pagination);
|
|
@@ -2310,6 +2418,7 @@ export class Store {
|
|
|
2310
2418
|
parentRaceId: optionalString(row, "parent_race_id"),
|
|
2311
2419
|
name: requiredString(row, "name"),
|
|
2312
2420
|
description: requiredString(row, "description"),
|
|
2421
|
+
...(row.child_count === undefined ? {} : { childCount: numberValue(row, "child_count") }),
|
|
2313
2422
|
...(includeMarkdown
|
|
2314
2423
|
? { settings, settingsMarkdown: settingsMarkdownFromList(settings), settingsSections }
|
|
2315
2424
|
: { settings: [], settingsCount: settingsSections.length }),
|
|
@@ -4100,7 +4209,8 @@ export class Store {
|
|
|
4100
4209
|
FROM analysis_tasks WHERE work_id = ?`, workId) ?? {};
|
|
4101
4210
|
const total = numberValue(statsRow, "total");
|
|
4102
4211
|
const page = paginationSql(pagination);
|
|
4103
|
-
const rows = this.db.all(`SELECT task.id, task.model_id, task.task_type, task.scope_json, task.status, task.progress,
|
|
4212
|
+
const rows = this.db.all(`SELECT task.id, task.model_id, task.task_type, task.scope_json, task.status, task.progress,
|
|
4213
|
+
task.attempt_count, task.next_attempt_at, task.last_attempt_at, task.created_at, task.updated_at,
|
|
4104
4214
|
model.display_name AS model_display_name, model.model_id AS model_api_id
|
|
4105
4215
|
FROM analysis_tasks task
|
|
4106
4216
|
LEFT JOIN models model ON model.id = task.model_id
|
|
@@ -4136,11 +4246,56 @@ export class Store {
|
|
|
4136
4246
|
const row = this.db.get("SELECT COUNT(*) AS value FROM analysis_tasks WHERE work_id = ? AND status = 'running'", workId);
|
|
4137
4247
|
return numberValue(row ?? {}, "value");
|
|
4138
4248
|
}
|
|
4249
|
+
listAutoRunWorkIds() {
|
|
4250
|
+
return this.db.all("SELECT work_id FROM work_ai_settings WHERE auto_run_enabled = 1 ORDER BY work_id").map((row) => requiredString(row, "work_id"));
|
|
4251
|
+
}
|
|
4252
|
+
claimPendingTask(taskId, runningLimit) {
|
|
4253
|
+
return this.db.transaction(() => {
|
|
4254
|
+
const current = this.getTask(taskId);
|
|
4255
|
+
if (current.status !== "pending")
|
|
4256
|
+
return null;
|
|
4257
|
+
if (current.nextAttemptAt && String(current.nextAttemptAt) > now())
|
|
4258
|
+
return null;
|
|
4259
|
+
if (runningLimit !== undefined && this.countRunningTasks(String(current.workId)) >= runningLimit)
|
|
4260
|
+
return null;
|
|
4261
|
+
const timestamp = now();
|
|
4262
|
+
const claimed = this.db.run(`UPDATE analysis_tasks
|
|
4263
|
+
SET status = 'running', progress = 5, attempt_count = attempt_count + 1,
|
|
4264
|
+
next_attempt_at = NULL, last_attempt_at = ?, updated_at = ?
|
|
4265
|
+
WHERE id = ? AND status = 'pending' AND (next_attempt_at IS NULL OR next_attempt_at <= ?)`, timestamp, timestamp, taskId, timestamp);
|
|
4266
|
+
return claimed.changes === 1 ? this.getTask(taskId) : null;
|
|
4267
|
+
});
|
|
4268
|
+
}
|
|
4139
4269
|
listOldestPendingTaskIds(workId, limit) {
|
|
4140
4270
|
if (limit <= 0)
|
|
4141
4271
|
return [];
|
|
4142
4272
|
return this.db.all(`SELECT id FROM analysis_tasks WHERE work_id = ? AND status = 'pending'
|
|
4143
|
-
|
|
4273
|
+
AND (next_attempt_at IS NULL OR next_attempt_at <= ?)
|
|
4274
|
+
ORDER BY created_at ASC, id ASC LIMIT ?`, workId, now(), limit).map((row) => requiredString(row, "id"));
|
|
4275
|
+
}
|
|
4276
|
+
nextPendingTaskAttemptAt(workId) {
|
|
4277
|
+
const row = this.db.get(`SELECT MIN(next_attempt_at) AS value FROM analysis_tasks
|
|
4278
|
+
WHERE work_id = ? AND status = 'pending' AND next_attempt_at IS NOT NULL`, workId);
|
|
4279
|
+
return row?.value === null || row?.value === undefined ? null : String(row.value);
|
|
4280
|
+
}
|
|
4281
|
+
countAutoRunAttemptsToday(workId) {
|
|
4282
|
+
const row = this.db.get(`SELECT COUNT(*) AS value FROM analysis_tasks
|
|
4283
|
+
WHERE work_id = ? AND last_attempt_at >= strftime('%Y-%m-%dT00:00:00.000Z', 'now')`, workId);
|
|
4284
|
+
return numberValue(row ?? {}, "value");
|
|
4285
|
+
}
|
|
4286
|
+
rescheduleTask(taskId, failure, nextAttemptAt) {
|
|
4287
|
+
const current = this.getTask(taskId);
|
|
4288
|
+
if (current.status !== "running")
|
|
4289
|
+
return current;
|
|
4290
|
+
const failures = Array.isArray(current.failures) ? [...current.failures, failure].slice(-10) : [failure];
|
|
4291
|
+
this.db.run(`UPDATE analysis_tasks
|
|
4292
|
+
SET status = 'pending', progress = 0, failure_json = ?, next_attempt_at = ?, updated_at = ?
|
|
4293
|
+
WHERE id = ? AND status = 'running'`, JSON.stringify(failures), nextAttemptAt, now(), taskId);
|
|
4294
|
+
this.audit(String(current.workId), "task.retry-scheduled", "analysis-task", taskId, {
|
|
4295
|
+
attemptCount: current.attemptCount,
|
|
4296
|
+
nextAttemptAt
|
|
4297
|
+
});
|
|
4298
|
+
return this.getTask(taskId);
|
|
4144
4299
|
}
|
|
4145
4300
|
countPendingTasks(workId) {
|
|
4146
4301
|
const row = this.db.get("SELECT COUNT(*) AS value FROM analysis_tasks WHERE work_id = ? AND status = 'pending'", workId);
|
|
@@ -5030,6 +5185,9 @@ export class Store {
|
|
|
5030
5185
|
result: taskResult,
|
|
5031
5186
|
failures: json(requiredString(row, "failure_json"), []),
|
|
5032
5187
|
sourceVersions: json(requiredString(row, "source_versions_json"), {}),
|
|
5188
|
+
attemptCount: numberValue(row, "attempt_count"),
|
|
5189
|
+
nextAttemptAt: row.next_attempt_at === null || row.next_attempt_at === undefined ? null : String(row.next_attempt_at),
|
|
5190
|
+
lastAttemptAt: row.last_attempt_at === null || row.last_attempt_at === undefined ? null : String(row.last_attempt_at),
|
|
5033
5191
|
createdAt: requiredString(row, "created_at"),
|
|
5034
5192
|
updatedAt: requiredString(row, "updated_at")
|
|
5035
5193
|
};
|
|
@@ -5044,6 +5202,9 @@ export class Store {
|
|
|
5044
5202
|
scopeSummaryWithoutCharacterNames: this.taskScopeSummaryFromMaps(scope, chapterSummaries, volumeTitles, new Map(), false),
|
|
5045
5203
|
status: requiredString(row, "status"),
|
|
5046
5204
|
progress: numberValue(row, "progress"),
|
|
5205
|
+
attemptCount: numberValue(row, "attempt_count"),
|
|
5206
|
+
nextAttemptAt: row.next_attempt_at === null || row.next_attempt_at === undefined ? null : String(row.next_attempt_at),
|
|
5207
|
+
lastAttemptAt: row.last_attempt_at === null || row.last_attempt_at === undefined ? null : String(row.last_attempt_at),
|
|
5047
5208
|
createdAt: requiredString(row, "created_at"),
|
|
5048
5209
|
updatedAt: requiredString(row, "updated_at")
|
|
5049
5210
|
};
|