@musnows/scriverse 0.6.4 → 0.6.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 CHANGED
@@ -373,7 +373,7 @@ const AGENT_TOOL_DEFINITIONS = {
373
373
  type: "function",
374
374
  function: {
375
375
  name: "search_story_entities",
376
- description: "按短关键词在结构化作品实体中进行元数据、精确全文和拼音混合检索:设定、人物(含 Markdown 档案章节)、种族、组织、时间线、关系、大纲和伏笔。不是语义问答;请传入实体名、别名、标题、拼音或短关键词,不要传入自然语言整句。结果按综合相关度排序;人物结果含 sectionId 时可再调用 read_character_sections 精读。无匹配时改用更短关键词,或改用 story_index / grep。",
376
+ description: "按短关键词在结构化作品实体中进行元数据、精确全文和拼音混合检索:设定、人物(含 Markdown 档案章节)、种族、组织、时间线、关系、大纲和伏笔。人物、种族、组织结果分别包含权威布尔状态 isDead、isExtinct、isDissolved;只有值为 true 才能判定该角色已死亡、该种族已灭绝或该组织已解散,字段为 false 时必须视为仍存活、未灭绝或未解散,禁止根据正文情节自行改判。不是语义问答;请传入实体名、别名、标题、拼音或短关键词,不要传入自然语言整句。结果按综合相关度排序;人物结果含 sectionId 时可再调用 read_character_sections 精读。无匹配时改用更短关键词,或改用 story_index / grep。",
377
377
  parameters: { type: "object", properties: { query: { type: "string", minLength: 1, maxLength: 200 }, categories: { type: "array", items: { type: "string", enum: ["setting", "character", "race", "organization", "timeline", "relationship", "outline", "foreshadow"] }, maxItems: 8 }, limit: { type: "integer", minimum: 1, maximum: 30, default: 30 }, cursor: agentToolCursorParameter }, required: ["query"], additionalProperties: false }
378
378
  }
379
379
  },
@@ -381,7 +381,7 @@ const AGENT_TOOL_DEFINITIONS = {
381
381
  type: "function",
382
382
  function: {
383
383
  name: "read_character_sections",
384
- description: "读取指定人物 Markdown 档案章节的摘要或原文。先通过 search_story_entities 获取 sectionId;每次最多读取 3 个章节。",
384
+ description: "读取指定人物 Markdown 档案章节的摘要或原文,并返回该人物的权威 isDead 状态。只有 isDead=true 才能判定人物已死亡;isDead=false 时必须视为仍存活,禁止根据章节内容自行改判。先通过 search_story_entities 获取 sectionId;每次最多读取 3 个章节。",
385
385
  parameters: { type: "object", properties: { sectionIds: { type: "array", items: { type: "string" }, minItems: 1, maxItems: 3 }, include: { type: "string", enum: ["summary", "content", "both"] }, cursor: agentToolCursorParameter }, required: ["sectionIds"], additionalProperties: false }
386
386
  }
387
387
  },
@@ -397,7 +397,7 @@ const AGENT_TOOL_DEFINITIONS = {
397
397
  type: "function",
398
398
  function: {
399
399
  name: "recall_self",
400
- description: "回忆与当前扮演角色自身有关的资料。只能读取自己的角色卡、人物档案章节,以及自己参与的关系、时间线和正文片段;不能指定或查询其他角色。",
400
+ description: "回忆与当前扮演角色自身有关的资料。角色、种族、组织状态分别以 isDead、isExtinct、isDissolved 为唯一权威标识;只有值为 true 才能判定已死亡、已灭绝或已解散,字段为 false 时必须视为仍存活、未灭绝或未解散,禁止根据回忆、正文或剧情暗示自行改判。只能读取自己的角色卡、人物档案章节,以及自己参与的关系、时间线和正文片段;不能指定或查询其他角色。",
401
401
  parameters: { type: "object", properties: { query: { type: "string", maxLength: 200, default: "", description: "可选的回忆关键词;留空时返回角色自身的核心资料。" }, categories: { type: "array", items: { type: "string", enum: ["profile", "sections", "relationships", "timeline", "chapters"] }, maxItems: 5 }, cursor: agentToolCursorParameter }, additionalProperties: false }
402
402
  }
403
403
  }
@@ -1006,10 +1006,8 @@ export class ContextBuilder {
1006
1006
  const includeAutomaticContext = scope.type !== "none" && scope.suppressAutomaticContext !== true;
1007
1007
  const settingsOnly = scope.type === "settings";
1008
1008
  const isProseScope = PROSE_CONTEXT_SCOPE_TYPES.has(scope.type);
1009
- const includeSettingInfo = includeAutomaticContext
1010
- && isProseScope
1011
- && !settingsOnly
1012
- && scope.includeSettingInfo !== false;
1009
+ const includeSettingInfo = !settingsOnly && scope.suppressAutomaticContext !== true && (scope.includeSettingInfo === true
1010
+ || (includeAutomaticContext && isProseScope && scope.includeSettingInfo !== false));
1013
1011
  const constraints = includeAutomaticContext
1014
1012
  ? [wrapAiContextRegion("work", `作品:${String(work.title)}\n作者:${String(work.author) || "未填写"}`)]
1015
1013
  : [];
@@ -3233,9 +3231,14 @@ export class AiManager {
3233
3231
  buildContextPlan(input, model, existingBudget, persistKeywordInjections = false) {
3234
3232
  const budget = existingBudget ?? this.contextBudget(input, model);
3235
3233
  const roleplayCharacterId = this.roleplayCharacterId(input.workId, input.conversationId);
3234
+ const settings = this.store.getWorkAiSettings(input.workId);
3235
+ const configuredScope = {
3236
+ ...input.scope,
3237
+ includeSettingInfo: settings.alwaysIncludeSettingInfo === true ? true : input.scope.includeSettingInfo
3238
+ };
3236
3239
  const baseScope = roleplayCharacterId
3237
3240
  ? {
3238
- ...input.scope,
3241
+ ...configuredScope,
3239
3242
  type: "none",
3240
3243
  suppressAutomaticContext: true,
3241
3244
  includeBookSummary: false,
@@ -3243,9 +3246,8 @@ export class AiManager {
3243
3246
  volumeId: undefined,
3244
3247
  selection: undefined
3245
3248
  }
3246
- : input.scope;
3249
+ : configuredScope;
3247
3250
  const contextWindow = numberValue(model, "context_window") || DEFAULT_CONTEXT_WINDOW;
3248
- const settings = this.store.getWorkAiSettings(input.workId);
3249
3251
  const percentage = Math.min(90, Math.max(1, Number(settings.bookSummaryContextPercent) || 50));
3250
3252
  const workContextBudgetTokens = Number(budget.workContextBudgetTokens) || 256;
3251
3253
  const bookSummaryMaximumTokens = baseScope.includeBookSummary || baseScope.type === "book" || baseScope.type === "volume"
@@ -3260,9 +3262,8 @@ export class AiManager {
3260
3262
  const injected = conversationId
3261
3263
  ? this.store.getAiConversationInjectedEntities(conversationId, workId)
3262
3264
  : { characters: [], races: [], organizations: [] };
3263
- const proseSettingInfoOn = PROSE_CONTEXT_SCOPE_TYPES.has(scope.type)
3264
- && scope.suppressAutomaticContext !== true
3265
- && scope.includeSettingInfo !== false;
3265
+ const proseSettingInfoOn = scope.suppressAutomaticContext !== true && (scope.includeSettingInfo === true || (PROSE_CONTEXT_SCOPE_TYPES.has(scope.type)
3266
+ && scope.includeSettingInfo !== false));
3266
3267
  const matches = matchKeywordEntities(this.store, workId, instruction, {
3267
3268
  excludeCharacterIds: [
3268
3269
  ...(scope.characterIds ?? []),
@@ -3314,9 +3315,11 @@ export class AiManager {
3314
3315
  delete profile.sections;
3315
3316
  const roleCard = {
3316
3317
  name: character.name,
3318
+ isDead: character.isDead,
3317
3319
  code: character.code,
3318
3320
  aliases: character.aliases,
3319
3321
  species: character.species,
3322
+ race: character.race,
3320
3323
  organizations: character.organizations,
3321
3324
  attributes: character.attributes,
3322
3325
  profile,
@@ -3460,9 +3463,11 @@ export class AiManager {
3460
3463
  const record = {
3461
3464
  category: "profile",
3462
3465
  name: character.name,
3466
+ isDead: character.isDead,
3463
3467
  code: character.code,
3464
3468
  aliases: character.aliases,
3465
3469
  species: character.species,
3470
+ race: character.race,
3466
3471
  organizations: character.organizations,
3467
3472
  attributes: character.attributes,
3468
3473
  profile,
@@ -3691,6 +3696,7 @@ export class AiManager {
3691
3696
  sectionId,
3692
3697
  characterId: section.characterId,
3693
3698
  characterName: character.name,
3699
+ isDead: character.isDead,
3694
3700
  title: section.title,
3695
3701
  sectionType: section.sectionType,
3696
3702
  versionNo: section.versionNo,
@@ -6422,7 +6428,7 @@ export class AiManager {
6422
6428
  if (String(item.workId) !== workId)
6423
6429
  return null;
6424
6430
  return source(`人物档案:${String(item.name)}`, {
6425
- name: item.name, aliases: item.aliases, code: item.code, species: item.species, race: item.race,
6431
+ name: item.name, isDead: item.isDead, aliases: item.aliases, code: item.code, species: item.species, race: item.race,
6426
6432
  organizations: item.organizations, attributes: item.attributes, profile: item.profile,
6427
6433
  currentState: item.currentState, lockedFields: item.lockedFields,
6428
6434
  profileSections: this.store.listCharacterProfileSections(sourceId).map((section) => ({
@@ -6439,6 +6445,7 @@ export class AiManager {
6439
6445
  return null;
6440
6446
  return source(`种族设定:${String(item.name)}`, {
6441
6447
  name: item.name,
6448
+ isExtinct: item.isExtinct,
6442
6449
  description: item.description,
6443
6450
  racePath: item.lineage.map((entry) => entry.name).join(" / "),
6444
6451
  lineage: item.lineage,
@@ -6451,7 +6458,7 @@ export class AiManager {
6451
6458
  if (String(item.workId) !== workId)
6452
6459
  return null;
6453
6460
  return source(`组织设定:${String(item.name)}`, {
6454
- name: item.name, description: item.description, settings: item.settings, members: item.members
6461
+ name: item.name, isDissolved: item.isDissolved, description: item.description, settings: item.settings, members: item.members
6455
6462
  }, item.versionNo);
6456
6463
  }
6457
6464
  if (sourceType === "timeline-track") {