narraeon 0.5.6 → 0.6.0
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/README.md +3 -1
- package/README.zh-CN.md +3 -1
- package/dist/node/protocol/appPreferences.js +4 -2
- package/dist/node/protocol/gameplay.js +69 -0
- package/dist/node/protocol/playFailure.js +13 -0
- package/dist/node/protocol/protagonistTemplates.js +13 -0
- package/dist/node/protocol/resolution.js +274 -0
- package/dist/node/protocol/v1.js +40 -19
- package/dist/node/protocol/worldArchives.js +7 -0
- package/dist/node/runtime/RuntimeErrorLog.js +95 -0
- package/dist/node/runtime/V1Runtime.js +103 -8
- package/dist/node/runtime/archive/WorldArchiveZip.js +202 -0
- package/dist/node/runtime/archive/WorldArchives.js +389 -0
- package/dist/node/runtime/config/AppPreferencesStore.js +23 -10
- package/dist/node/runtime/config/ProtagonistTemplateStore.js +134 -0
- package/dist/node/runtime/content/ContentWorkspace.js +15 -2
- package/dist/node/runtime/content/CurrentTreeContentLibrary.js +43 -2
- package/dist/node/runtime/content/FileNativeContentTree.js +8 -1
- package/dist/node/runtime/history/StoryExport.js +33 -0
- package/dist/node/runtime/model/FileNativeModelAdapters.js +34 -2
- package/dist/node/runtime/model/ModelHost.js +12 -1
- package/dist/node/runtime/model/ModelHostStream.js +11 -3
- package/dist/node/runtime/play/FileNativePlayAdvanceStore.js +37 -1
- package/dist/node/runtime/play/FileNativePlayPresetStore.js +48 -3
- package/dist/node/runtime/play/FileNativePlayTimelineStore.js +87 -4
- package/dist/node/runtime/play/LegacyModelBindingFailure.js +10 -0
- package/dist/node/runtime/play/OrderedPlayPrompts.js +68 -6
- package/dist/node/runtime/play/PlayCallChain.js +177 -57
- package/dist/node/runtime/play/PlayCallChainError.js +3 -1
- package/dist/node/runtime/play/PlayContinuity.js +3 -20
- package/dist/node/runtime/play/PlayFailure.js +20 -0
- package/dist/node/runtime/play/PlayTraceRetention.js +3 -11
- package/dist/node/runtime/play/TabletopResolution.js +372 -0
- package/dist/node/runtime/play/TabletopRules.js +141 -0
- package/dist/node/runtime/prompt/FileNativePromptCompiler.js +49 -32
- package/dist/node/runtime/prompt/FileNativeToolRegistry.js +37 -4
- package/dist/node/runtime/setting/FileNativeSettingImprovementStore.js +4 -1
- package/dist/node/runtime/setting/SettingAuthoringTransaction.js +56 -13
- package/dist/node/runtime/setting/SettingImprovementSession.js +6 -4
- package/dist/node/runtime/world/FileNativeWorldStore.js +207 -40
- package/dist/node/runtime/world/WorldActivity.js +143 -0
- package/dist/node/runtime/world-revision/FileNativeWorldRevisionStore.js +2 -0
- package/dist/node/runtime/world-revision/WorldRevisionAuthoringTransaction.js +35 -6
- package/dist/node/runtime/world-revision/WorldRevisionSession.js +9 -5
- package/dist/node/server/ConversationStream.js +2 -0
- package/dist/node/server/createServer.js +48 -0
- package/dist/node/shared/default-preset-host.js +10 -6
- package/dist/node/shared/ordered-author-prompts.js +8 -0
- package/dist/node/shared/ordered-play-prompts.js +25 -2
- package/dist/node/shared/sample-packages/index.js +10 -0
- package/dist/node/shared/sample-packages/rainy-inn-en.js +194 -0
- package/dist/node/shared/sample-packages/rainy-inn-zh.js +194 -0
- package/dist/node/shared/tabletop-guidance.js +100 -0
- package/dist/web/assets/index-BJ-1Mb0e.css +1 -0
- package/dist/web/assets/index-BgBL8G-A.js +1323 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -2
- package/dist/web/assets/index-BH8NyuE4.js +0 -1233
- package/dist/web/assets/index-CVN48xrw.css +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { parseDocument } from "yaml";
|
|
2
|
+
import { isMap, isSeq, parseDocument } from "yaml";
|
|
3
3
|
import { builtinPlayPrompts, isPromptMessageRole, } from "../../shared/ordered-play-prompts.js";
|
|
4
4
|
/** The same strict permission gate is used by portable imports and structured saves. */
|
|
5
5
|
export function parseOrderedPlayPrompts(value, catalog = builtinPlayPrompts("en"), worldRequired = true) {
|
|
@@ -24,20 +24,23 @@ export function parseOrderedPlayPrompts(value, catalog = builtinPlayPrompts("en"
|
|
|
24
24
|
!isPromptMessageRole(item.messageRole))
|
|
25
25
|
return fail();
|
|
26
26
|
const messageRole = item.messageRole === undefined ? {} : { messageRole: item.messageRole };
|
|
27
|
-
const exact = (keys) => Object.keys(item).
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const exact = (keys, optional = []) => Object.keys(item).every((key) => keys.includes(key) ||
|
|
28
|
+
optional.includes(key) ||
|
|
29
|
+
key === "messageRole" ||
|
|
30
|
+
key === "id" ||
|
|
31
|
+
key === "kind") && keys.every((key) => Object.hasOwn(item, key));
|
|
30
32
|
if (item.kind === "world" && exact(["id", "kind"])) {
|
|
31
33
|
worlds++;
|
|
32
34
|
return { id: item.id, kind: "world", ...messageRole };
|
|
33
35
|
}
|
|
34
36
|
if (item.kind === "user" &&
|
|
35
|
-
exact(["id", "kind", "name", "enabled", "body"]) &&
|
|
37
|
+
exact(["id", "kind", "name", "enabled", "body"], ["gameplay"]) &&
|
|
36
38
|
typeof item.name === "string" &&
|
|
37
39
|
item.name.trim().length > 0 &&
|
|
38
40
|
/^[^\r\n\0]{1,160}$/u.test(item.name) &&
|
|
39
41
|
typeof item.body === "string" &&
|
|
40
|
-
typeof item.enabled === "boolean"
|
|
42
|
+
typeof item.enabled === "boolean" &&
|
|
43
|
+
(item.gameplay === undefined || item.gameplay === "tabletop"))
|
|
41
44
|
return {
|
|
42
45
|
id: item.id,
|
|
43
46
|
kind: "user",
|
|
@@ -45,6 +48,9 @@ export function parseOrderedPlayPrompts(value, catalog = builtinPlayPrompts("en"
|
|
|
45
48
|
enabled: item.enabled,
|
|
46
49
|
body: item.body,
|
|
47
50
|
...messageRole,
|
|
51
|
+
...(item.gameplay === "tabletop"
|
|
52
|
+
? { gameplay: "tabletop" }
|
|
53
|
+
: {}),
|
|
48
54
|
};
|
|
49
55
|
const builtin = catalog.find((entry) => entry.id === item.builtin);
|
|
50
56
|
if (item.kind !== "builtin" ||
|
|
@@ -70,6 +76,54 @@ export function parseOrderedPlayPrompts(value, catalog = builtinPlayPrompts("en"
|
|
|
70
76
|
return fail();
|
|
71
77
|
return entries;
|
|
72
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Insert the tabletop builtins that an ordered preset does not list yet.
|
|
81
|
+
* play.tabletop goes just before the world placeholder and author.tabletop just
|
|
82
|
+
* after author.guidance. Files that are not ordered v2 or do not parse come back
|
|
83
|
+
* unchanged, and nothing else in them is rewritten. The same object is returned
|
|
84
|
+
* when nothing needs inserting, so callers can detect a change by identity.
|
|
85
|
+
*/
|
|
86
|
+
export function withTabletopPromptBuiltins(files) {
|
|
87
|
+
const source = files["preset.yaml"];
|
|
88
|
+
if (source === undefined)
|
|
89
|
+
return files;
|
|
90
|
+
const document = parseDocument(source, { uniqueKeys: true });
|
|
91
|
+
if (document.errors.length > 0 ||
|
|
92
|
+
document.warnings.length > 0 ||
|
|
93
|
+
!isMap(document.contents) ||
|
|
94
|
+
document.get("format") !== "narraeon.play-preset/v2")
|
|
95
|
+
return files;
|
|
96
|
+
let changed = false;
|
|
97
|
+
const playPrompts = document.get("playPrompts", true);
|
|
98
|
+
if (isSeq(playPrompts) && !hasEntry(playPrompts, "play.tabletop")) {
|
|
99
|
+
const world = playPrompts.items.findIndex((item) => entryField(item, "kind") === "world");
|
|
100
|
+
playPrompts.items.splice(world < 0 ? playPrompts.items.length : world, 0, document.createNode({
|
|
101
|
+
id: "play.tabletop",
|
|
102
|
+
kind: "builtin",
|
|
103
|
+
builtin: "play.tabletop",
|
|
104
|
+
enabled: true,
|
|
105
|
+
}));
|
|
106
|
+
changed = true;
|
|
107
|
+
}
|
|
108
|
+
const authorPrompts = document.get("authorPrompts", true);
|
|
109
|
+
if (isSeq(authorPrompts) && !hasEntry(authorPrompts, "author.tabletop")) {
|
|
110
|
+
const guidance = authorPrompts.items.findIndex((item) => entryField(item, "id") === "author.guidance");
|
|
111
|
+
authorPrompts.items.splice(guidance < 0 ? authorPrompts.items.length : guidance + 1, 0, document.createNode({
|
|
112
|
+
id: "author.tabletop",
|
|
113
|
+
kind: "builtin",
|
|
114
|
+
builtin: "author.tabletop",
|
|
115
|
+
enabled: true,
|
|
116
|
+
}));
|
|
117
|
+
changed = true;
|
|
118
|
+
}
|
|
119
|
+
return changed ? { ...files, "preset.yaml": document.toString() } : files;
|
|
120
|
+
}
|
|
121
|
+
function hasEntry(sequence, id) {
|
|
122
|
+
return sequence.items.some((item) => entryField(item, "id") === id);
|
|
123
|
+
}
|
|
124
|
+
function entryField(item, key) {
|
|
125
|
+
return isMap(item) ? item.get(key) : undefined;
|
|
126
|
+
}
|
|
73
127
|
/** Recognized v1 content becomes user text, never a locked builtin inferred from a path. */
|
|
74
128
|
export function migrateLegacyPlayPrompts(files, narrative, excludedPaths = []) {
|
|
75
129
|
const document = parseDocument(files["frame.yaml"] ?? "", {
|
|
@@ -185,5 +239,13 @@ export function migrateLegacyPlayPrompts(files, narrative, excludedPaths = []) {
|
|
|
185
239
|
if ((path.startsWith("blocks/") || path.startsWith("prompts/")) &&
|
|
186
240
|
path.endsWith(".md"))
|
|
187
241
|
add(path, false);
|
|
242
|
+
// The tabletop builtin joins converted presets just before the world placeholder.
|
|
243
|
+
const worldIndex = entries.findIndex((entry) => entry.kind === "world");
|
|
244
|
+
entries.splice(worldIndex, 0, {
|
|
245
|
+
id: "play.tabletop",
|
|
246
|
+
kind: "builtin",
|
|
247
|
+
builtin: "play.tabletop",
|
|
248
|
+
enabled: true,
|
|
249
|
+
});
|
|
188
250
|
return entries;
|
|
189
251
|
}
|