narraeon 0.4.0 → 0.5.1

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.
Files changed (76) hide show
  1. package/dist/node/protocol/appPreferences.js +25 -0
  2. package/dist/node/protocol/conversationObservation.js +67 -0
  3. package/dist/node/protocol/v1.js +186 -34
  4. package/dist/node/protocol/worldExtensions.js +16 -0
  5. package/dist/node/protocol/worldMaintenance.js +77 -0
  6. package/dist/node/protocol/worldPromptDiagnostics.js +1 -0
  7. package/dist/node/runtime/ConversationChanges.js +24 -0
  8. package/dist/node/runtime/V1Runtime.js +445 -121
  9. package/dist/node/runtime/artifact/FileNativeArtifactStore.js +326 -12
  10. package/dist/node/runtime/authoring/AuthoringRequestSnapshot.js +63 -0
  11. package/dist/node/runtime/authoring/ModelToolConversation.js +218 -0
  12. package/dist/node/runtime/config/AppPreferencesStore.js +46 -17
  13. package/dist/node/runtime/content/ContentTreeFingerprint.js +13 -0
  14. package/dist/node/runtime/content/ContentWorkspace.js +43 -13
  15. package/dist/node/runtime/content/CurrentTreeContentLibrary.js +128 -46
  16. package/dist/node/runtime/content/FileNativeContentTree.js +28 -10
  17. package/dist/node/runtime/content/PackageFollowups.js +80 -0
  18. package/dist/node/runtime/extension/FrontendExtensionBundle.js +19 -14
  19. package/dist/node/runtime/extension/PackageScriptPermissions.js +70 -0
  20. package/dist/node/runtime/extension/WorldExtensionControls.js +205 -0
  21. package/dist/node/runtime/extension/WorldExtensionRequests.js +64 -0
  22. package/dist/node/runtime/model/FileNativeModelAdapters.js +21 -466
  23. package/dist/node/runtime/model/ModelConnectionStore.js +13 -0
  24. package/dist/node/runtime/model/ModelHost.js +31 -1
  25. package/dist/node/runtime/model/ModelHostStream.js +51 -5
  26. package/dist/node/runtime/play/FileNativeContinuityCorrection.js +55 -45
  27. package/dist/node/runtime/play/FileNativePlayPresetStore.js +256 -238
  28. package/dist/node/runtime/play/FileNativePlayTimelineStore.js +118 -9
  29. package/dist/node/runtime/play/OrderedFollowups.js +71 -0
  30. package/dist/node/runtime/play/OrderedPlayPrompts.js +180 -0
  31. package/dist/node/runtime/play/PlayCallChain.js +814 -61
  32. package/dist/node/runtime/play/PlayContinuity.js +88 -0
  33. package/dist/node/runtime/play/PlayDocumentTools.js +205 -287
  34. package/dist/node/runtime/play/PlayFollowupRequests.js +34 -3
  35. package/dist/node/runtime/play/PlayPresetWorkbench.js +45 -54
  36. package/dist/node/runtime/play/PlayPromptRun.js +86 -0
  37. package/dist/node/runtime/prompt/FileNativePromptCompiler.js +670 -93
  38. package/dist/node/runtime/prompt/FileNativeToolRegistry.js +37 -21
  39. package/dist/node/runtime/prompt/PromptCompilationCodec.js +322 -0
  40. package/dist/node/runtime/prompt/WorldMaintenanceReport.js +251 -0
  41. package/dist/node/runtime/prompt/WorldMaterialCoverage.js +83 -0
  42. package/dist/node/runtime/prompt/WorldPromptDiagnostics.js +185 -0
  43. package/dist/node/runtime/setting/FileNativeSettingImprovementStore.js +1027 -0
  44. package/dist/node/runtime/setting/SettingAuthoringTransaction.js +1339 -0
  45. package/dist/node/runtime/setting/SettingImprovementSession.js +714 -0
  46. package/dist/node/runtime/world/FileNativeAuthorityV3.js +88 -1
  47. package/dist/node/runtime/world/FileNativeWorldStore.js +292 -27
  48. package/dist/node/runtime/world/PlayerViewBindings.js +30 -0
  49. package/dist/node/runtime/world/PlayerViewRenderer.js +27 -34
  50. package/dist/node/runtime/world/WorldDocumentMaintenance.js +174 -0
  51. package/dist/node/runtime/world/WorldDocumentStore.js +166 -96
  52. package/dist/node/runtime/world/WorldOperationCoordinator.js +103 -2
  53. package/dist/node/runtime/world-revision/FileNativeWorldRevisionStore.js +696 -0
  54. package/dist/node/runtime/world-revision/WorldRevisionAuthoringTransaction.js +380 -0
  55. package/dist/node/runtime/world-revision/WorldRevisionSession.js +709 -0
  56. package/dist/node/runtime/world-revision/WorldRevisionWorkspace.js +494 -0
  57. package/dist/node/server/ConversationStream.js +109 -0
  58. package/dist/node/server/createServer.js +5 -1
  59. package/dist/node/shared/artifact-payload-contract.js +123 -0
  60. package/dist/node/shared/default-play-prompts.js +25 -45
  61. package/dist/node/shared/default-preset-host.js +114 -138
  62. package/dist/node/shared/default-setting-improvement-prompt.js +52 -38
  63. package/dist/node/shared/display-regex.js +114 -0
  64. package/dist/node/shared/first-party-action-choices.js +1 -6
  65. package/dist/node/shared/first-party-player-view.js +1 -6
  66. package/dist/node/shared/ordered-author-prompts.js +64 -0
  67. package/dist/node/shared/ordered-followups.js +42 -0
  68. package/dist/node/shared/ordered-play-prompts.js +73 -0
  69. package/dist/web/assets/index-DG85hpWC.css +1 -0
  70. package/dist/web/assets/index-DfxvCjb6.js +1207 -0
  71. package/dist/web/index.html +2 -2
  72. package/package.json +1 -1
  73. package/dist/node/runtime/model/SettingAuthorStream.js +0 -21
  74. package/dist/node/runtime/setting/DocumentCandidateSettingImprovement.js +0 -1731
  75. package/dist/web/assets/index-D8YKfmNG.js +0 -1192
  76. package/dist/web/assets/index-Xa0s35CJ.css +0 -1
@@ -0,0 +1,123 @@
1
+ export function validatePlayPresetArtifactPayload(contract, value) {
2
+ if (contract === undefined)
3
+ return { ok: true };
4
+ if (!isJsonValueValue(value))
5
+ return {
6
+ ok: false,
7
+ message: "JSON artifact payload must be a valid JSON value",
8
+ };
9
+ return validatePayloadNode(contract, value, "$", 0);
10
+ }
11
+ function validatePayloadNode(contract, value, path, depth) {
12
+ if (depth > 32)
13
+ return { ok: false, message: `${path} payload nesting exceeds 32 levels` };
14
+ const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
15
+ const typeMatches = contract.type === actual ||
16
+ (contract.type === "number" && actual === "number") ||
17
+ (contract.type === "integer" &&
18
+ actual === "number" &&
19
+ Number.isInteger(value));
20
+ if (!typeMatches)
21
+ return {
22
+ ok: false,
23
+ message: `${path} payload type must be ${contract.type}; received ${actual}`,
24
+ };
25
+ if (contract.maxBytes !== undefined) {
26
+ const encoded = JSON.stringify(value);
27
+ if (encoded === undefined ||
28
+ new TextEncoder().encode(encoded).byteLength > contract.maxBytes)
29
+ return {
30
+ ok: false,
31
+ message: `${path} payload exceeds its declared ${contract.maxBytes}-byte limit`,
32
+ };
33
+ }
34
+ if (contract.type === "string") {
35
+ const text = value;
36
+ if (contract.minLength !== undefined &&
37
+ [...text].length < contract.minLength)
38
+ return {
39
+ ok: false,
40
+ message: `${path} text length is less than ${contract.minLength}`,
41
+ };
42
+ if (contract.maxLength !== undefined &&
43
+ [...text].length > contract.maxLength)
44
+ return {
45
+ ok: false,
46
+ message: `${path} text length exceeds ${contract.maxLength}`,
47
+ };
48
+ }
49
+ if (contract.type === "array") {
50
+ const entries = value;
51
+ if (contract.minItems !== undefined && entries.length < contract.minItems)
52
+ return {
53
+ ok: false,
54
+ message: `${path} has fewer than ${contract.minItems} items`,
55
+ };
56
+ if (contract.maxItems !== undefined && entries.length > contract.maxItems)
57
+ return {
58
+ ok: false,
59
+ message: `${path} has more than ${contract.maxItems} items`,
60
+ };
61
+ const seen = new Set();
62
+ for (const [index, entry] of entries.entries()) {
63
+ if (contract.items !== undefined) {
64
+ const result = validatePayloadNode(contract.items, entry, `${path}[${index}]`, depth + 1);
65
+ if (!result.ok)
66
+ return result;
67
+ }
68
+ if (contract.uniqueBy !== undefined && isRecordValue(entry)) {
69
+ const unique = entry[contract.uniqueBy];
70
+ if (typeof unique !== "string" &&
71
+ typeof unique !== "number" &&
72
+ typeof unique !== "boolean")
73
+ return {
74
+ ok: false,
75
+ message: `${path}[${index}].${contract.uniqueBy} must be a uniquely comparable scalar`,
76
+ };
77
+ const key = JSON.stringify(unique);
78
+ if (seen.has(key))
79
+ return {
80
+ ok: false,
81
+ message: `${path} ${contract.uniqueBy} values cannot be duplicated`,
82
+ };
83
+ seen.add(key);
84
+ }
85
+ }
86
+ }
87
+ if (contract.type === "object") {
88
+ const object = value;
89
+ const properties = contract.properties ?? {};
90
+ for (const required of contract.required ?? [])
91
+ if (!(required in object))
92
+ return { ok: false, message: `${path}.${required} is required` };
93
+ if (contract.additionalProperties === false)
94
+ for (const key of Object.keys(object))
95
+ if (!(key in properties))
96
+ return {
97
+ ok: false,
98
+ message: `${path}.${key} is not a declared field`,
99
+ };
100
+ for (const [key, child] of Object.entries(properties)) {
101
+ if (!(key in object))
102
+ continue;
103
+ const result = validatePayloadNode(child, object[key], `${path}.${key}`, depth + 1);
104
+ if (!result.ok)
105
+ return result;
106
+ }
107
+ }
108
+ return { ok: true };
109
+ }
110
+ function isJsonValueValue(value) {
111
+ if (value === null || typeof value === "string" || typeof value === "boolean")
112
+ return true;
113
+ if (typeof value === "number")
114
+ return Number.isFinite(value);
115
+ if (Array.isArray(value))
116
+ return value.every(isJsonValueValue);
117
+ if (!isRecordValue(value))
118
+ return false;
119
+ return Object.values(value).every(isJsonValueValue);
120
+ }
121
+ function isRecordValue(value) {
122
+ return typeof value === "object" && value !== null && !Array.isArray(value);
123
+ }
@@ -3,79 +3,59 @@
3
3
  * first-party presets. Portable presets still receive ordinary editable file
4
4
  * contents; this module only prevents the shipped starting points from
5
5
  * drifting apart. The general adjudication and state-maintenance criteria live
6
- * in the host preset, which every mode loads.
6
+ * in independently editable host recommendation blocks.
7
7
  */
8
8
  export const defaultNarrationPromptZhCN = `# 玩家可见叙事规则
9
9
 
10
- 当你决定输出玩家可见故事正文时,写成互动式小说,不写成裁决报告、工具日志或主持流程说明。哪些事已经发生,以当前调用链里已经作出的判断、已经写入的世界变化和玩家明确实施的行动为准;补充不改变结果的表演细节是允许的。
10
+ 世界内游玩输出互动式小说正文,让玩家读到这次经历。以已加载材料、已经裁决的结果和成功提交的变化为依据;表达方式可以丰富,不能改变谁在哪、拿着什么、是否受伤或承诺是否成立。尝试不自动成为成功,角色声称不自动成为事实。
11
11
 
12
- 这一段是互动式小说的正文,不是过程报告。读者是玩家本人,他要的是读下去的体验,不是一份“这次交互发生了什么”的交代。
12
+ ## 承接与表现
13
13
 
14
- ## 怎么写
14
+ 有新玩家输入时,把其中明确行动或台词自然接入场景,补足不改变选择的表达细节,再写相应反应。已经演过的部分不用重述,不以“你说要……”机械复读。原生对话末尾已有主持正文、其后没有新玩家输入时,本次是空输入续写:从那段正文的最后局面继续,只推进既有授权动作、NPC 和环境。不重新回答已经回应的问题,不复位已完成的递接或走动,不把旧玩家输入再演一次,也不替玩家增加决定。
15
15
 
16
- 从玩家这次输入写起,把它扩写成完整的场景——他具体怎么做的、什么语气神态、当时的姿态和距离——再接着写它引出的后续。不要用“你说要去找他”这类回指句开头,直接把那个动作演出来。
16
+ 本轮新发生且玩家能感知的结果,要成为具体可读的事:物品怎样递接、人物如何离开、态度变化怎样在话语或行动中显露。文档中补录旧结果、去重和整理不要求再次演出。界面数值不能代替事件表现,叙事也不能与当前值冲突。未向玩家表露的判断和场外事实无需用旁白揭露。
17
17
 
18
- 让环境、光线、声音、他人的小动作和身体反应参与进来。情绪和关系尽量侧写,通过动作走形、话说到一半停住、视线躲闪来呈现,而不是直接判定“他很紧张”。玩家没有互动的 NPC 也在做自己的事,让场面里同时发生的事不必都与玩家有关。
18
+ 具体表演细节随最终叙事保存,可按需追溯;不要假定每次请求自动带着全部旧段落。必须持续保存的结果按状态维护政策处理,不能只留在检查点收尾原文中。
19
19
 
20
- 当前调用链写进世界文档、而玩家角色感知得到的变化,这一段必须演出来:不是复述“他的态度变好了”,是让他做出或说出能看出这一点的那句话、那个动作。写进了文档却没进叙事,玩家就读不到它,对他等于没有发生。已经确定的结果同样不能改:谁在哪、拿着什么、答应了什么,都要保持一致。在这个骨架上尽管写具体——他拿起什么、说了哪句话、手上停在哪个动作——这些细节会随本段叙事一起提交,后续模型请求读得到它们。
20
+ ## 停在哪里
21
21
 
22
- 以玩家原文、已加载的世界材料和当前调用链已经确定的结果为准。结果既包括写进文档的持续变化,也包括只在当前场面成立的直接后果;两者都不得被叙事掩盖或改写。玩家只表达愿望、意图或尝试时,不要擅自把愿望写成已经达成。
22
+ 在当前行动与反应形成有内容的局面、或下一次关键选择需要玩家时停笔。具体人物动作、原话或环境变化都可以承接下一段;有意义的沉默、独处、休息和等待也可以自然结束。不要为了结尾形式让 NPC 硬添动作、邀请或承诺。
23
23
 
24
- ## 怎么收尾
24
+ 避免“轮到你了”“你打算怎么做”及把同一句套话改成“众人等你开口”的机械交接,也不要在结尾列选项或重复总结局势。真正发生的注视或等待可以描写,不必强行消除。
25
25
 
26
- **最后一句写某个人做的一件具体的事,或说的一句具体的话。** 他问了什么,原话写出来;他把东西递过来,写他怎么递的;他站起身往门口走,写他走了。这句话本身要有内容,读者读的是这件事,不是读“该我了”。
26
+ ## 输出边界
27
27
 
28
- 轮到玩家,是他从这件事里自己得出的结论,不需要你告诉他。所以结尾不写场面的状态,只写事件:
28
+ 世界内叙事只写小说正文,可以分多个自然段,不加标题、清单、裁决报告、工具日志或幕后说明。篇幅由场面的分量决定,停笔位置限制推进范围,不要求把已经授权的场面写得潦草。失败、NPC 自主行动和没有文档变化都可以形成完整叙事。
29
29
 
30
- - 不写“没人接话”“屋里安静下来”“空气凝住了”——沉默不是事件,用它收尾等于什么都没发生。
31
- - 不写“两道视线落回你身上”“他等着你的下文”“所有人都在等你开口”——这是把“轮到你了”翻译成了场面语言,和直接问“你打算怎么做”是同一件事,只是穿了小说的皮。
32
- - 不写“你打算怎么做”“接下来你会怎么办”“你可以选择……”,也不要在结尾把局势总结一遍或列出他有哪些选项。
30
+ 本次只有世界外查询或维护时,按请求简洁回答或说明整理结果,不为满足小说形式添加动作、对话或时间推进。混合请求中的维护要求不成为角色台词或行动。
33
31
 
34
- 如果写到最后发现场上确实没人有动作可做,那说明这一段收早了:让某个人先做点什么——开口、起身、动手、走近——再停。
35
-
36
- ## 边界
37
-
38
- 玩家可见文本只写小说正文,可以分多个自然段;不要标题、清单、解释、工具过程或幕后说明。停笔位置约束的是故事推进到哪里,不是可以写多厚——在这个范围内把场面、反应和氛围写足。
39
-
40
- 篇幅由这一刻的分量决定,不是每段都写成同一个长度。过场收快;玩家真正在意的那一刻停下来,把那几秒拆开写。
41
-
42
- 不要替玩家作出**本该由他决定**的事——改变目标立场、答应或拒绝、交出或收下、动手或收手。为执行他已表达的意图而演出的连带动作、应答和具体措辞不算替玩家决定;玩家的尝试失败、NPC 作出自主反应、当前没有任何文档变化,也都不妨碍正常叙事。
32
+ 玩家的关键决定仍归玩家;表现自然感官与动作细节不能替他表达立场、感情、同意或承诺。已经提交的行动不能用一句普通改口当作从未发生。
43
33
  `;
44
34
  export const defaultNarrationPromptEn = `# Player-visible narrative rules
45
35
 
46
- Whenever you produce player-visible story text, write it as an interactive novel, not as an adjudication report, tool log, or explanation of the hosting process. What has happened is determined by decisions already made in the current call chain, world changes already written, and actions the player explicitly carried out. You may add performance details that do not alter those outcomes.
47
-
48
- This is the body of an interactive novel, not a process report. The reader is the player, who wants an experience worth continuing, not a recap of “what happened in this interaction.”
49
-
50
- ## How to write
51
-
52
- Begin with the player's current input. Expand it into a complete scene—how the action is performed, the player's tone and expression, posture, and distance—then continue into the consequences it produces. Do not open with a backward reference such as “You said you would go find them.” Put the action directly on the page.
53
-
54
- Bring in the environment, light, sound, other characters' small movements, and physical reactions. Imply emotion and relationships through a movement going wrong, a sentence breaking off, or a gaze turning away instead of declaring “they are nervous.” NPCs the player is not engaging with still have their own business; simultaneous events do not all need to revolve around the player.
36
+ For in-world play, write the body of an interactive novel so the player experiences this passage. Ground it in loaded material, adjudicated outcomes and successfully committed changes. Enrich expression without changing who is where, what they hold, whether an injury occurred or a promise was made. Attempts are not automatically successes; character claims are not automatically facts.
55
37
 
56
- Any change written to a world document in the current call chain that the player character can perceive must be dramatized here. Do not say “their attitude improved”; show the line or gesture that makes the change visible. If a change exists in a document but not in the narrative, the player cannot read it and it effectively did not happen for them. Do not alter settled results either: keep consistent who is where, what they hold, and what they promised. Within that structure, be specific—what someone picks up, the exact words they say, where a hand pauses. These details are committed with the narrative and remain available to later model requests.
38
+ ## Continuation and dramatization
57
39
 
58
- Follow the player's original text, the loaded world material, and outcomes already settled in the current call chain. Outcomes include durable changes written to documents and direct consequences that hold only in the current scene. The narrative may neither hide nor rewrite either kind. When the player expresses only a wish, intention, or attempt, do not silently turn it into an accomplished result.
40
+ When there is new player input, naturally stage its explicit action or dialogue with details that preserve the choice, then its reactions. Do not restate parts already performed or mechanically open with “You said you would…”. When the native conversation ends with narrator prose and no newer player input, this is an empty continuation: resume from that prose’s final situation, advancing only already authorized actions, NPCs and the environment. Do not answer an already answered question again, reset completed handovers or movements, perform the old player input again, or add a new player decision.
59
41
 
60
- ## How to end
42
+ Make new perceivable outcomes this turn concrete: an object handed over, a person leaving, an attitude expressed through words or action. Delayed recording, deduplication and maintenance do not require performing old events again. Interface values do not replace dramatization, and prose must agree with current values. Unexpressed judgments and offstage facts need not be revealed in narration.
61
43
 
62
- **Make the final sentence a specific action someone takes or a specific line they say.** If someone asks a question, write the actual question. If they hand something over, show how. If they stand and walk toward the door, write that movement. The sentence must have content; the reader should be reading the event, not a disguised message that “it is your turn.”
44
+ Specific performance details are saved with final narrative and can be retrieved when needed; do not assume every request automatically includes every earlier passage. Handle required durable results under the state-maintenance policy instead of leaving them only in a checkpoint's closing prose.
63
45
 
64
- The player can infer that it is their turn. Do not state the condition of the scene at the end; end on an event:
46
+ ## Where to stop
65
47
 
66
- - Do not end with “no one answers,” “the room falls quiet,” or “the air freezes.” Silence is not an event, and ending on it means nothing happened.
67
- - Do not end with “two pairs of eyes return to you,” “they wait for you to continue,” or “everyone waits for you to speak.” Those phrases merely translate “your turn” into scenic language and are equivalent to asking “What do you do?”, dressed in prose.
68
- - Do not write “What do you do?”, “What happens next?”, or “You could choose…”. Do not summarize the situation or list the player's options at the end.
48
+ Stop when the action and reactions form a meaningful situation or a consequential choice needs the player. A specific action, actual line of dialogue or environmental change can lead onward; meaningful silence, solitude, rest and waiting can also close naturally. Do not invent an NPC action, invitation or promise to satisfy an ending format.
69
49
 
70
- If you reach the end and nobody in the scene has an action to take, the passage stopped too early. Let someone do something—speak, stand, act, or approach—then stop.
50
+ Avoid mechanical handoffs such as “Your turn”, “What do you do?” or their stock substitute “Everyone waits for you to speak”. Do not end by listing options or repeating a situation summary. Actual attention or waiting may be described without being forcibly removed.
71
51
 
72
- ## Boundaries
52
+ ## Output boundaries
73
53
 
74
- Player-visible text contains only the novel's prose and may use several natural paragraphs. Do not include headings, lists, explanations, tool activity, or backstage notes. The stopping point limits how far the story advances, not how fully the moment can be rendered; within that boundary, give the scene, reactions, and atmosphere enough space.
54
+ In-world narrative uses only the novel's prose, in several natural paragraphs if useful, without headings, lists, adjudication reports, tool logs or backstage notes. Let the weight of the moment determine length. A stopping point limits advancement, not the care given to the authorized scene. Failure, NPC autonomy and no document changes can all yield a complete passage.
75
55
 
76
- Let the weight of the moment determine length instead of forcing every passage into the same size. Move quickly through transitions; when the player truly cares about a moment, slow down and separate those few seconds.
56
+ If this request is solely out-of-world inquiry or maintenance, answer or explain the consolidation briefly as requested without adding actions, dialogue or time passage to satisfy novel form. Maintenance instructions within a mixed request do not become character speech or actions.
77
57
 
78
- Do not make a decision that **belongs to the player**—changing goals or allegiance, accepting or refusing, giving or taking something, striking or holding back. Supporting movements, replies, and exact wording that carry out an intention the player already expressed do not take agency away. A failed attempt, an NPC's autonomous reaction, or a response with no document changes can all still produce normal narrative.
58
+ Consequential decisions belong to the player. Sensory and movement details must not express a stance, feeling, consent or promise for them. A later ordinary change of mind does not mean an already committed action never happened.
79
59
  `;
80
60
  export const defaultNarrationPrompt = defaultNarrationPromptEn;
81
61
  export function defaultNarrationPromptForLocale(locale) {