@musnows/scriverse 0.8.4 → 0.8.5
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-stream-timeout.js +9 -6
- package/dist/ai-stream-timeout.js.map +1 -1
- package/dist/ai.js +32 -6
- package/dist/ai.js.map +1 -1
- package/dist/app.js +10 -4
- package/dist/app.js.map +1 -1
- package/dist/database.js +48 -2
- package/dist/database.js.map +1 -1
- package/dist/public/app.js +253 -51
- package/dist/public/index.html +2 -2
- package/dist/public/styles.css +9 -0
- package/dist/server-runtime.js +4 -2
- package/dist/server-runtime.js.map +1 -1
- package/dist/store.js +12 -3
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
export const AI_STREAM_IDLE_TIMEOUT_SECONDS_ENV = "SCRIVERSE_AI_STREAM_IDLE_TIMEOUT_SECONDS";
|
|
2
|
-
export const DEFAULT_AI_STREAM_IDLE_TIMEOUT_SECONDS =
|
|
3
|
-
export const MIN_AI_STREAM_IDLE_TIMEOUT_SECONDS =
|
|
4
|
-
export const MAX_AI_STREAM_IDLE_TIMEOUT_SECONDS =
|
|
2
|
+
export const DEFAULT_AI_STREAM_IDLE_TIMEOUT_SECONDS = 90;
|
|
3
|
+
export const MIN_AI_STREAM_IDLE_TIMEOUT_SECONDS = 30;
|
|
4
|
+
export const MAX_AI_STREAM_IDLE_TIMEOUT_SECONDS = 600;
|
|
5
5
|
export const DEFAULT_AI_STREAM_IDLE_TIMEOUT_MS = DEFAULT_AI_STREAM_IDLE_TIMEOUT_SECONDS * 1_000;
|
|
6
|
+
export function normalizeAiStreamIdleTimeoutSeconds(value) {
|
|
7
|
+
if (!Number.isSafeInteger(value))
|
|
8
|
+
return DEFAULT_AI_STREAM_IDLE_TIMEOUT_SECONDS;
|
|
9
|
+
return Math.min(MAX_AI_STREAM_IDLE_TIMEOUT_SECONDS, Math.max(MIN_AI_STREAM_IDLE_TIMEOUT_SECONDS, value));
|
|
10
|
+
}
|
|
6
11
|
export function resolveAiStreamIdleTimeoutSeconds(environment = process.env) {
|
|
7
12
|
const raw = environment[AI_STREAM_IDLE_TIMEOUT_SECONDS_ENV]?.trim() ?? "";
|
|
8
13
|
if (!/^\d+$/u.test(raw))
|
|
9
14
|
return DEFAULT_AI_STREAM_IDLE_TIMEOUT_SECONDS;
|
|
10
15
|
const configured = Number(raw);
|
|
11
|
-
|
|
12
|
-
return DEFAULT_AI_STREAM_IDLE_TIMEOUT_SECONDS;
|
|
13
|
-
return Math.min(MAX_AI_STREAM_IDLE_TIMEOUT_SECONDS, Math.max(MIN_AI_STREAM_IDLE_TIMEOUT_SECONDS, configured));
|
|
16
|
+
return normalizeAiStreamIdleTimeoutSeconds(configured);
|
|
14
17
|
}
|
|
15
18
|
export function resolveAiStreamIdleTimeoutMs(environment = process.env) {
|
|
16
19
|
return resolveAiStreamIdleTimeoutSeconds(environment) * 1_000;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-stream-timeout.js","sourceRoot":"","sources":["../src/ai-stream-timeout.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kCAAkC,GAAG,0CAA0C,CAAC;AAC7F,MAAM,CAAC,MAAM,sCAAsC,GAAG,EAAE,CAAC;AACzD,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAC;AACrD,MAAM,CAAC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AACtD,MAAM,CAAC,MAAM,iCAAiC,GAAG,sCAAsC,GAAG,KAAK,CAAC;AAEhG,MAAM,UAAU,iCAAiC,CAAC,cAAiC,OAAO,CAAC,GAAG;IAC5F,MAAM,GAAG,GAAG,WAAW,CAAC,kCAAkC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,sCAAsC,CAAC;IACvE,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/B,
|
|
1
|
+
{"version":3,"file":"ai-stream-timeout.js","sourceRoot":"","sources":["../src/ai-stream-timeout.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kCAAkC,GAAG,0CAA0C,CAAC;AAC7F,MAAM,CAAC,MAAM,sCAAsC,GAAG,EAAE,CAAC;AACzD,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAC;AACrD,MAAM,CAAC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AACtD,MAAM,CAAC,MAAM,iCAAiC,GAAG,sCAAsC,GAAG,KAAK,CAAC;AAEhG,MAAM,UAAU,mCAAmC,CAAC,KAAa;IAC/D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;QAAE,OAAO,sCAAsC,CAAC;IAChF,OAAO,IAAI,CAAC,GAAG,CACb,kCAAkC,EAClC,IAAI,CAAC,GAAG,CAAC,kCAAkC,EAAE,KAAK,CAAC,CACpD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,cAAiC,OAAO,CAAC,GAAG;IAC5F,MAAM,GAAG,GAAG,WAAW,CAAC,kCAAkC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,sCAAsC,CAAC;IACvE,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,mCAAmC,CAAC,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,cAAiC,OAAO,CAAC,GAAG;IACvF,OAAO,iCAAiC,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;AAChE,CAAC"}
|
package/dist/ai.js
CHANGED
|
@@ -3,7 +3,7 @@ import { buildCompletionRequestBody, isAiProviderProtocol, normalizeProviderBase
|
|
|
3
3
|
import { AGENT_TOOL_RESULT_MAX_CHARS, DEFAULT_AGENT_TOOL_CALL_GLOBAL_MULTIPLIER, MIN_AGENT_TOOL_CALL_LIMIT, agentToolCallGlobalLimit, agentToolCallQuotaNoticeBudgetChars, agentToolCallQuotaUsedAfterCompact, agentToolCallSoftWarningThreshold, clampAgentToolCallGlobalMultiplier, paginateToolResultRecords, resolveMaxAgentToolCallLimit, shouldRejectAgentToolCalls, shouldRejectGlobalToolCalls, structuralToolResultRecords, withAgentToolCallQuotaNotice } from "./ai-tool-results.js";
|
|
4
4
|
import { AiConnectivityTestGate, hashAiConnectivityConfiguration } from "./ai-connectivity-test.js";
|
|
5
5
|
import { aiHttpRetryCount, aiHttpRetryDelayMs, normalizeAiRetryPolicy } from "./ai-retry.js";
|
|
6
|
-
import { DEFAULT_AI_STREAM_IDLE_TIMEOUT_MS } from "./ai-stream-timeout.js";
|
|
6
|
+
import { DEFAULT_AI_STREAM_IDLE_TIMEOUT_MS, normalizeAiStreamIdleTimeoutSeconds } from "./ai-stream-timeout.js";
|
|
7
7
|
import { characterExtractionHash, characterExtractionSelectionFingerprint, editableCharacterExtractionCandidate, normalizeCharacterExtractionCandidate, parseStoredCharacterExtractionCandidates } from "./character-extraction.js";
|
|
8
8
|
import { PLATFORM_AI_WORK_ID } from "./database.js";
|
|
9
9
|
import { AppError, notFound } from "./errors.js";
|
|
@@ -284,7 +284,7 @@ function thinkingParameters(provider, model) {
|
|
|
284
284
|
return { thinking: { type: thinkingEnabled ? "enabled" : "disabled" }, ...effortParameters };
|
|
285
285
|
}
|
|
286
286
|
const CONFIGURED_AGENT_TOOL_IDS = ["story_index", "read_chapters", "grep", "search_story_entities", "read_character_sections", "search_drafts", "image", "calculate_time"];
|
|
287
|
-
const AGENT_TOOL_IDS = [...CONFIGURED_AGENT_TOOL_IDS, "recall_self", "recall_relationship"];
|
|
287
|
+
const AGENT_TOOL_IDS = [...CONFIGURED_AGENT_TOOL_IDS, "recall_self", "recall_relationship", "recall_story"];
|
|
288
288
|
const AGENT_TOOL_READ_MODULES = {
|
|
289
289
|
story_index: ["prose"],
|
|
290
290
|
read_chapters: ["prose"],
|
|
@@ -595,6 +595,14 @@ const AGENT_TOOL_DEFINITIONS = {
|
|
|
595
595
|
parameters: { type: "object", properties: { characters: { type: "array", items: { type: "string", minLength: 1, maxLength: 200 }, maxItems: 20, default: [], description: "可选的对方角色姓名、别名或角色 ID 列表;留空时只列出有关系的角色。" }, cursor: agentToolCursorParameter }, additionalProperties: false }
|
|
596
596
|
}
|
|
597
597
|
},
|
|
598
|
+
recall_story: {
|
|
599
|
+
type: "function",
|
|
600
|
+
function: {
|
|
601
|
+
name: "recall_story",
|
|
602
|
+
description: "查询当前作品已保存正文中的关键词,返回匹配的完整段落及章节标题和 ID。用于回忆最近发生的故事情节、场景或原文措辞;只能读取当前正文,不会读取设定库或作者想法。",
|
|
603
|
+
parameters: { type: "object", properties: { keyword: { type: "string", minLength: 1, maxLength: 200 }, limit: { type: "integer", minimum: 1, maximum: 100, default: 20 }, cursor: agentToolCursorParameter }, required: ["keyword"], additionalProperties: false }
|
|
604
|
+
}
|
|
605
|
+
},
|
|
598
606
|
calculate_time: {
|
|
599
607
|
type: "function",
|
|
600
608
|
function: {
|
|
@@ -1695,6 +1703,12 @@ export class AiManager {
|
|
|
1695
1703
|
backoffRetryCount: this.retryPolicy.backoffRetryCount
|
|
1696
1704
|
});
|
|
1697
1705
|
}
|
|
1706
|
+
setInteractiveStreamIdleTimeoutSeconds(seconds) {
|
|
1707
|
+
this.interactiveStreamIdleTimeoutMs = normalizeAiStreamIdleTimeoutSeconds(seconds) * 1_000;
|
|
1708
|
+
logger.info("ai.manager.stream_idle_timeout_updated", {
|
|
1709
|
+
interactiveStreamIdleTimeoutMs: this.interactiveStreamIdleTimeoutMs
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1698
1712
|
getPlatformTokenUsage(timezoneOffset) {
|
|
1699
1713
|
return this.getTokenUsage(null, timezoneOffset, true);
|
|
1700
1714
|
}
|
|
@@ -2830,7 +2844,13 @@ export class AiManager {
|
|
|
2830
2844
|
return this.getModel(modelId);
|
|
2831
2845
|
}
|
|
2832
2846
|
deleteModel(modelId) {
|
|
2833
|
-
this.getModelRow(modelId);
|
|
2847
|
+
const model = this.getModelRow(modelId);
|
|
2848
|
+
const providerId = stringValue(model, "provider_id");
|
|
2849
|
+
this.store.audit(PLATFORM_AI_WORK_ID, "model.deleted", "model", modelId, {
|
|
2850
|
+
providerId,
|
|
2851
|
+
modelId: stringValue(model, "model_id"),
|
|
2852
|
+
displayName: stringValue(model, "display_name")
|
|
2853
|
+
});
|
|
2834
2854
|
this.store.db.transaction(() => {
|
|
2835
2855
|
this.clearImageToolModelReferences(modelId);
|
|
2836
2856
|
this.store.db.run("DELETE FROM models WHERE id = ?", modelId);
|
|
@@ -4387,6 +4407,7 @@ export class AiManager {
|
|
|
4387
4407
|
...(enabledToolIds.includes("calculate_time") ? ["涉及日期差值或从日期推算目标日期时,使用 calculate_time;不要凭记忆估算日期。"] : []),
|
|
4388
4408
|
"当回应涉及角色自身的身份、经历、所见所闻或记忆,而角色卡与对话历史不足以确定时,使用 recall_self 回忆;它不能指定或查询其他角色。",
|
|
4389
4409
|
...(enabledToolIds.includes("recall_relationship") ? ["当回应涉及当前角色与其他角色的关系、关系类型、状态或相处经历,而角色卡与对话历史不足以确定时,使用 recall_relationship;先不传 characters 获取有关系的角色列表,再传入 characters 数组获取一个或多个指定角色的关系详情。它只能查询当前角色参与的关系,不能查询两个其他角色之间的关系。"] : []),
|
|
4410
|
+
...(enabledToolIds.includes("recall_story") ? ["当回应涉及已经写入故事的近期情节、场景或具体措辞,而角色自身记忆与对话历史不足以确定时,使用 recall_story 按关键词查询当前正文。"] : []),
|
|
4390
4411
|
"把返回内容自然地当作角色自己的记忆、认知或感受来表达。没有返回的信息就以符合角色的方式表现为不知道、没见过、记不清或不确定,不得补用全知信息。"
|
|
4391
4412
|
].join("\n")
|
|
4392
4413
|
: enabledToolIds.length > 0
|
|
@@ -4668,6 +4689,9 @@ export class AiManager {
|
|
|
4668
4689
|
if (canReadWorkModule(permissions, "relationships") && (!requested || requested.has("recall_relationship"))) {
|
|
4669
4690
|
roleplayTools.push("recall_relationship");
|
|
4670
4691
|
}
|
|
4692
|
+
if (canReadWorkModule(permissions, "prose") && (!requested || requested.has("recall_story"))) {
|
|
4693
|
+
roleplayTools.push("recall_story");
|
|
4694
|
+
}
|
|
4671
4695
|
roleplayTools.push("calculate_time");
|
|
4672
4696
|
return roleplayTools;
|
|
4673
4697
|
}
|
|
@@ -4843,8 +4867,9 @@ export class AiManager {
|
|
|
4843
4867
|
: name === "image" ? imageArguments
|
|
4844
4868
|
: name === "recall_self" ? recallSelfArguments
|
|
4845
4869
|
: name === "recall_relationship" ? recallRelationshipArguments
|
|
4846
|
-
: name === "
|
|
4847
|
-
:
|
|
4870
|
+
: name === "recall_story" ? grepArguments
|
|
4871
|
+
: name === "calculate_time" ? calculateTimeArguments
|
|
4872
|
+
: null;
|
|
4848
4873
|
const toolId = AGENT_TOOL_IDS.includes(name) ? name : null;
|
|
4849
4874
|
const enabledTools = allowedToolIds ?? new Set(this.store.getWorkAiSettings(workId).agentTools
|
|
4850
4875
|
.filter((item) => typeof item === "string" && AGENT_TOOL_IDS.includes(item)));
|
|
@@ -4856,6 +4881,7 @@ export class AiManager {
|
|
|
4856
4881
|
? (toolId === "calculate_time" && enabledTools.has(toolId))
|
|
4857
4882
|
|| (toolId === "recall_self" && enabledTools.has(toolId) && canReadWorkModule(permissions, "characters"))
|
|
4858
4883
|
|| (toolId === "recall_relationship" && enabledTools.has(toolId) && canReadWorkModule(permissions, "characters") && canReadWorkModule(permissions, "relationships"))
|
|
4884
|
+
|| (toolId === "recall_story" && enabledTools.has(toolId) && canReadWorkModule(permissions, "prose"))
|
|
4859
4885
|
: Boolean(configuredToolId && enabledTools.has(configuredToolId) && this.canReadWithAgentTool(permissions, configuredToolId));
|
|
4860
4886
|
if (!schema || !toolId || !toolAvailable) {
|
|
4861
4887
|
return {
|
|
@@ -5209,7 +5235,7 @@ export class AiManager {
|
|
|
5209
5235
|
}), maximumResultChars);
|
|
5210
5236
|
return { id: toolCall.id, name, calledAt, arguments: { chapterIds, include, ...(cursor > 0 ? { cursor } : {}) }, status: "completed", result };
|
|
5211
5237
|
}
|
|
5212
|
-
if (name === "grep") {
|
|
5238
|
+
if (name === "grep" || name === "recall_story") {
|
|
5213
5239
|
const { keyword, limit, cursor } = args;
|
|
5214
5240
|
const matches = this.store.searchChapterParagraphs(workId, keyword, limit, { excludeAuthorNotes: true })
|
|
5215
5241
|
.filter((match) => !scopedChapterIds || scopedChapterIds.has(String(match.chapterId)));
|