@musnows/scriverse 0.5.8 → 0.5.10
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 +355 -70
- package/dist/ai.js.map +1 -1
- package/dist/app.js +48 -37
- 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 +421 -64
- 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 +20 -7
- package/dist/public/race-hierarchy.js +0 -35
- package/dist/public/styles.css +36 -10
- package/dist/public/vditor-line-number-layout.d.ts +14 -0
- package/dist/public/vditor-line-number-layout.js +51 -0
- package/dist/relationship-search.js +21 -2
- package/dist/relationship-search.js.map +1 -1
- package/dist/store.js +137 -5
- 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/dist/version.js.map +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);
|
|
@@ -2208,6 +2274,19 @@ export class Store {
|
|
|
2208
2274
|
this.getWork(workId);
|
|
2209
2275
|
return this.db.all("SELECT * FROM races WHERE work_id = ? ORDER BY name", workId).map((row) => this.mapRace(row, includeMarkdown));
|
|
2210
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
|
+
}
|
|
2211
2290
|
listRacesPage(workId, pagination, includeMarkdown = true) {
|
|
2212
2291
|
this.getWork(workId);
|
|
2213
2292
|
const page = paginationSql(pagination);
|
|
@@ -2339,6 +2418,7 @@ export class Store {
|
|
|
2339
2418
|
parentRaceId: optionalString(row, "parent_race_id"),
|
|
2340
2419
|
name: requiredString(row, "name"),
|
|
2341
2420
|
description: requiredString(row, "description"),
|
|
2421
|
+
...(row.child_count === undefined ? {} : { childCount: numberValue(row, "child_count") }),
|
|
2342
2422
|
...(includeMarkdown
|
|
2343
2423
|
? { settings, settingsMarkdown: settingsMarkdownFromList(settings), settingsSections }
|
|
2344
2424
|
: { settings: [], settingsCount: settingsSections.length }),
|
|
@@ -4129,7 +4209,8 @@ export class Store {
|
|
|
4129
4209
|
FROM analysis_tasks WHERE work_id = ?`, workId) ?? {};
|
|
4130
4210
|
const total = numberValue(statsRow, "total");
|
|
4131
4211
|
const page = paginationSql(pagination);
|
|
4132
|
-
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,
|
|
4133
4214
|
model.display_name AS model_display_name, model.model_id AS model_api_id
|
|
4134
4215
|
FROM analysis_tasks task
|
|
4135
4216
|
LEFT JOIN models model ON model.id = task.model_id
|
|
@@ -4165,11 +4246,56 @@ export class Store {
|
|
|
4165
4246
|
const row = this.db.get("SELECT COUNT(*) AS value FROM analysis_tasks WHERE work_id = ? AND status = 'running'", workId);
|
|
4166
4247
|
return numberValue(row ?? {}, "value");
|
|
4167
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
|
+
}
|
|
4168
4269
|
listOldestPendingTaskIds(workId, limit) {
|
|
4169
4270
|
if (limit <= 0)
|
|
4170
4271
|
return [];
|
|
4171
4272
|
return this.db.all(`SELECT id FROM analysis_tasks WHERE work_id = ? AND status = 'pending'
|
|
4172
|
-
|
|
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);
|
|
4173
4299
|
}
|
|
4174
4300
|
countPendingTasks(workId) {
|
|
4175
4301
|
const row = this.db.get("SELECT COUNT(*) AS value FROM analysis_tasks WHERE work_id = ? AND status = 'pending'", workId);
|
|
@@ -5059,6 +5185,9 @@ export class Store {
|
|
|
5059
5185
|
result: taskResult,
|
|
5060
5186
|
failures: json(requiredString(row, "failure_json"), []),
|
|
5061
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),
|
|
5062
5191
|
createdAt: requiredString(row, "created_at"),
|
|
5063
5192
|
updatedAt: requiredString(row, "updated_at")
|
|
5064
5193
|
};
|
|
@@ -5073,6 +5202,9 @@ export class Store {
|
|
|
5073
5202
|
scopeSummaryWithoutCharacterNames: this.taskScopeSummaryFromMaps(scope, chapterSummaries, volumeTitles, new Map(), false),
|
|
5074
5203
|
status: requiredString(row, "status"),
|
|
5075
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),
|
|
5076
5208
|
createdAt: requiredString(row, "created_at"),
|
|
5077
5209
|
updatedAt: requiredString(row, "updated_at")
|
|
5078
5210
|
};
|