@musnows/scriverse 0.7.4 → 0.7.6
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 +49 -7
- package/dist/ai.js.map +1 -1
- package/dist/app.js +44 -45
- package/dist/app.js.map +1 -1
- package/dist/epub-export.js +42 -38
- package/dist/epub-export.js.map +1 -1
- package/dist/public/app.js +127 -54
- package/dist/public/index.html +6 -6
- package/dist/public/outline-board.d.ts +16 -10
- package/dist/public/outline-board.js +11 -105
- package/dist/public/reading-preview.d.ts +5 -1
- package/dist/public/reading-preview.js +17 -2
- package/dist/public/styles.css +11 -8
- package/dist/store.js +239 -63
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/dist/zip-stream.js +149 -0
- package/dist/zip-stream.js.map +1 -0
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -664,13 +664,7 @@ async function sendEpub(response, archive, title, fallbackStem) {
|
|
|
664
664
|
response.type(EPUB_MIME_TYPE);
|
|
665
665
|
response.setHeader("Content-Disposition", epubContentDisposition(title, fallbackStem));
|
|
666
666
|
response.setHeader("Cache-Control", "private, no-store");
|
|
667
|
-
await pipeline(archive
|
|
668
|
-
type: "nodebuffer",
|
|
669
|
-
// 逐条目压缩后再写入,确保首个 mimetype 本地头包含确定长度且没有额外字段。
|
|
670
|
-
streamFiles: false,
|
|
671
|
-
compression: "DEFLATE",
|
|
672
|
-
compressionOptions: { level: 6 }
|
|
673
|
-
}), response);
|
|
667
|
+
await pipeline(archive, response);
|
|
674
668
|
}
|
|
675
669
|
function parse(schema, value) {
|
|
676
670
|
return schema.parse(value);
|
|
@@ -1386,7 +1380,7 @@ export function createRuntime(options) {
|
|
|
1386
1380
|
});
|
|
1387
1381
|
app.delete("/api/works/:workId", async (request, response) => {
|
|
1388
1382
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1389
|
-
|
|
1383
|
+
ai.deleteWork(request.params.workId, input.expectedVersionNo);
|
|
1390
1384
|
noContent(response);
|
|
1391
1385
|
});
|
|
1392
1386
|
app.get("/api/works/:workId/cover", (request, response) => {
|
|
@@ -1584,7 +1578,21 @@ export function createRuntime(options) {
|
|
|
1584
1578
|
data(response, pagination ? store.listChapterOutlinesPage(request.params.workId, pagination) : store.listChapterOutlines(request.params.workId));
|
|
1585
1579
|
});
|
|
1586
1580
|
app.get("/api/works/:workId/outline-board", (request, response) => {
|
|
1587
|
-
|
|
1581
|
+
const query = parse(z.object({
|
|
1582
|
+
q: z.string().trim().max(200).default(""),
|
|
1583
|
+
volumeId: z.string().trim().max(200).default(""),
|
|
1584
|
+
outlineStatus: z.enum(["all", "empty", "draft", "ready", "completed"]).default("all"),
|
|
1585
|
+
foreshadowStatus: z.enum(["all", "none", "unresolved", "resolved", "abandoned"]).default("all"),
|
|
1586
|
+
sort: z.enum(["tree", "status", "foreshadows", "title"]).default("tree")
|
|
1587
|
+
}), request.query);
|
|
1588
|
+
const pagination = parsePagination(request.query) ?? { page: 1, limit: 30, offset: 0 };
|
|
1589
|
+
data(response, store.getChapterOutlineBoard(request.params.workId, {
|
|
1590
|
+
query: query.q,
|
|
1591
|
+
volumeId: query.volumeId,
|
|
1592
|
+
outlineStatus: query.outlineStatus,
|
|
1593
|
+
foreshadowStatus: query.foreshadowStatus,
|
|
1594
|
+
sort: query.sort
|
|
1595
|
+
}, pagination));
|
|
1588
1596
|
});
|
|
1589
1597
|
app.get("/api/chapters/:chapterId/outline", (request, response) => data(response, store.getChapterOutline(request.params.chapterId)));
|
|
1590
1598
|
app.put("/api/chapters/:chapterId/outline", (request, response) => {
|
|
@@ -2367,8 +2375,9 @@ export function createRuntime(options) {
|
|
|
2367
2375
|
modelId: identifier.optional(),
|
|
2368
2376
|
scope: contextSchema,
|
|
2369
2377
|
instruction: z.string().max(100_000).default(""),
|
|
2370
|
-
citations: aiCitationsSchema.optional()
|
|
2371
|
-
|
|
2378
|
+
citations: aiCitationsSchema.optional(),
|
|
2379
|
+
ignoreContextWarning: z.boolean().optional()
|
|
2380
|
+
}).strict(), request.body ?? {});
|
|
2372
2381
|
const conversation = store.getAiConversation(request.params.conversationId);
|
|
2373
2382
|
data(response, await ai.prepareConversationContext({
|
|
2374
2383
|
conversationId: request.params.conversationId,
|
|
@@ -2376,7 +2385,7 @@ export function createRuntime(options) {
|
|
|
2376
2385
|
modelId: input.modelId,
|
|
2377
2386
|
scope: input.scope,
|
|
2378
2387
|
instruction: instructionWithCitations(input.instruction, input.citations ?? [])
|
|
2379
|
-
}));
|
|
2388
|
+
}, { ignoreWarning: input.ignoreContextWarning === true }));
|
|
2380
2389
|
});
|
|
2381
2390
|
app.post("/api/ai-conversations/:conversationId/compact", async (request, response) => {
|
|
2382
2391
|
const input = parse(z.object({ modelId: identifier.optional(), scope: contextSchema }), request.body);
|
|
@@ -2484,8 +2493,9 @@ export function createRuntime(options) {
|
|
|
2484
2493
|
parameters: jsonObject.optional(),
|
|
2485
2494
|
citations: aiCitationsSchema.optional(),
|
|
2486
2495
|
conversationId: identifier.optional(),
|
|
2487
|
-
currentMessageId: identifier.optional()
|
|
2488
|
-
|
|
2496
|
+
currentMessageId: identifier.optional(),
|
|
2497
|
+
ignoreContextWarning: z.boolean().optional()
|
|
2498
|
+
}).strict(), request.body);
|
|
2489
2499
|
const providedIdempotencyKey = request.get("Idempotency-Key");
|
|
2490
2500
|
const idempotencyKey = providedIdempotencyKey
|
|
2491
2501
|
? parse(idempotencyKeySchema, providedIdempotencyKey)
|
|
@@ -2520,6 +2530,8 @@ export function createRuntime(options) {
|
|
|
2520
2530
|
let streamRequestId = null;
|
|
2521
2531
|
let streamRequestFinished = false;
|
|
2522
2532
|
let lastStreamLeaseTouchAt = Date.now();
|
|
2533
|
+
let preparedContext = null;
|
|
2534
|
+
let preparedConversation = null;
|
|
2523
2535
|
const startStream = () => {
|
|
2524
2536
|
if (response.headersSent)
|
|
2525
2537
|
return;
|
|
@@ -2541,31 +2553,27 @@ export function createRuntime(options) {
|
|
|
2541
2553
|
try {
|
|
2542
2554
|
if (!existingRequest) {
|
|
2543
2555
|
store.assertAiConversationStreamAvailable(conversationId);
|
|
2544
|
-
|
|
2556
|
+
preparedContext = await ai.prepareConversationContext({
|
|
2545
2557
|
conversationId,
|
|
2546
2558
|
workId: request.params.workId,
|
|
2547
2559
|
modelId: input.modelId,
|
|
2548
2560
|
scope: input.scope,
|
|
2549
2561
|
instruction: resolvedInstruction,
|
|
2550
2562
|
excludeConversationMessageId: input.currentMessageId
|
|
2551
|
-
});
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
conversationId,
|
|
2555
|
-
workId: request.params.workId,
|
|
2556
|
-
modelId: input.modelId,
|
|
2557
|
-
scope: input.scope,
|
|
2558
|
-
instruction: resolvedInstruction,
|
|
2559
|
-
excludeConversationMessageId: input.currentMessageId
|
|
2560
|
-
});
|
|
2563
|
+
}, { ignoreWarning: input.ignoreContextWarning === true });
|
|
2564
|
+
preparedConversation = redactAiConversation(store.getAiConversationSummary(conversationId), permissions);
|
|
2565
|
+
if (preparedContext.action === "warn") {
|
|
2561
2566
|
startStream();
|
|
2562
2567
|
sendEvent("ready", { streaming: true, idempotencyKey });
|
|
2563
2568
|
sendEvent("context", {
|
|
2564
|
-
...
|
|
2565
|
-
conversation:
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
+
...preparedContext,
|
|
2570
|
+
conversation: preparedConversation
|
|
2571
|
+
});
|
|
2572
|
+
sendEvent("complete", {
|
|
2573
|
+
warningOnly: true,
|
|
2574
|
+
conversationId,
|
|
2575
|
+
conversationTitle: conversation.title,
|
|
2576
|
+
contextUsage: preparedContext.usage
|
|
2569
2577
|
});
|
|
2570
2578
|
return;
|
|
2571
2579
|
}
|
|
@@ -2630,24 +2638,15 @@ export function createRuntime(options) {
|
|
|
2630
2638
|
}
|
|
2631
2639
|
return;
|
|
2632
2640
|
}
|
|
2641
|
+
if (preparedContext) {
|
|
2642
|
+
sendEvent("context", {
|
|
2643
|
+
...preparedContext,
|
|
2644
|
+
conversation: preparedConversation
|
|
2645
|
+
});
|
|
2646
|
+
}
|
|
2633
2647
|
const currentMessageId = String(begun.userMessage?.id ?? input.currentMessageId ?? "");
|
|
2634
2648
|
if (begun.userMessage)
|
|
2635
2649
|
sendEvent("user_message", { message: redactAiConversationMessage(begun.userMessage, permissions) });
|
|
2636
|
-
const prepared = await ai.prepareConversationContext({
|
|
2637
|
-
conversationId,
|
|
2638
|
-
workId: request.params.workId,
|
|
2639
|
-
modelId: input.modelId,
|
|
2640
|
-
scope: input.scope,
|
|
2641
|
-
instruction: resolvedInstruction,
|
|
2642
|
-
excludeConversationMessageId: currentMessageId
|
|
2643
|
-
}, { skipWarning: true });
|
|
2644
|
-
sendEvent("context", {
|
|
2645
|
-
...prepared,
|
|
2646
|
-
conversation: redactAiConversation({
|
|
2647
|
-
...store.getAiConversationSummary(conversationId),
|
|
2648
|
-
contextWarningPending: prepared.action === "warn"
|
|
2649
|
-
}, permissions)
|
|
2650
|
-
});
|
|
2651
2650
|
const suggestion = await ai.createStreamingChat({
|
|
2652
2651
|
workId: request.params.workId,
|
|
2653
2652
|
instruction: resolvedInstruction,
|