narraeon 0.3.1 → 0.5.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/dist/node/protocol/appPreferences.js +25 -0
- package/dist/node/protocol/conversationObservation.js +67 -0
- package/dist/node/protocol/v1.js +188 -34
- package/dist/node/protocol/worldExtensions.js +16 -0
- package/dist/node/protocol/worldMaintenance.js +77 -0
- package/dist/node/protocol/worldPromptDiagnostics.js +1 -0
- package/dist/node/runtime/ConversationChanges.js +24 -0
- package/dist/node/runtime/V1Runtime.js +447 -121
- package/dist/node/runtime/artifact/FileNativeArtifactStore.js +326 -12
- package/dist/node/runtime/authoring/AuthoringRequestSnapshot.js +63 -0
- package/dist/node/runtime/authoring/ModelToolConversation.js +218 -0
- package/dist/node/runtime/config/AppPreferencesStore.js +46 -17
- package/dist/node/runtime/content/ContentTreeFingerprint.js +13 -0
- package/dist/node/runtime/content/ContentWorkspace.js +43 -13
- package/dist/node/runtime/content/CurrentTreeContentLibrary.js +128 -46
- package/dist/node/runtime/content/FileNativeContentTree.js +28 -10
- package/dist/node/runtime/content/PackageFollowups.js +80 -0
- package/dist/node/runtime/extension/FrontendExtensionBundle.js +19 -14
- package/dist/node/runtime/extension/PackageScriptPermissions.js +70 -0
- package/dist/node/runtime/extension/WorldExtensionControls.js +205 -0
- package/dist/node/runtime/extension/WorldExtensionRequests.js +64 -0
- package/dist/node/runtime/model/FileNativeModelAdapters.js +21 -466
- package/dist/node/runtime/model/ModelConnectionStore.js +44 -10
- package/dist/node/runtime/model/ModelHost.js +31 -1
- package/dist/node/runtime/model/ModelHostStream.js +51 -5
- package/dist/node/runtime/play/FileNativeContinuityCorrection.js +55 -45
- package/dist/node/runtime/play/FileNativePlayPresetStore.js +256 -238
- package/dist/node/runtime/play/FileNativePlayTimelineStore.js +118 -9
- package/dist/node/runtime/play/OrderedFollowups.js +71 -0
- package/dist/node/runtime/play/OrderedPlayPrompts.js +180 -0
- package/dist/node/runtime/play/PlayCallChain.js +814 -61
- package/dist/node/runtime/play/PlayContinuity.js +88 -0
- package/dist/node/runtime/play/PlayDocumentTools.js +205 -287
- package/dist/node/runtime/play/PlayFollowupRequests.js +34 -3
- package/dist/node/runtime/play/PlayPresetWorkbench.js +45 -54
- package/dist/node/runtime/play/PlayPromptRun.js +86 -0
- package/dist/node/runtime/prompt/FileNativePromptCompiler.js +670 -93
- package/dist/node/runtime/prompt/FileNativeToolRegistry.js +37 -21
- package/dist/node/runtime/prompt/PromptCompilationCodec.js +322 -0
- package/dist/node/runtime/prompt/WorldMaintenanceReport.js +251 -0
- package/dist/node/runtime/prompt/WorldMaterialCoverage.js +83 -0
- package/dist/node/runtime/prompt/WorldPromptDiagnostics.js +185 -0
- package/dist/node/runtime/setting/FileNativeSettingImprovementStore.js +1027 -0
- package/dist/node/runtime/setting/SettingAuthoringTransaction.js +1339 -0
- package/dist/node/runtime/setting/SettingImprovementSession.js +714 -0
- package/dist/node/runtime/world/FileNativeAuthorityV3.js +88 -1
- package/dist/node/runtime/world/FileNativeWorldStore.js +292 -27
- package/dist/node/runtime/world/PlayerViewBindings.js +30 -0
- package/dist/node/runtime/world/PlayerViewRenderer.js +27 -34
- package/dist/node/runtime/world/WorldDocumentMaintenance.js +174 -0
- package/dist/node/runtime/world/WorldDocumentStore.js +166 -96
- package/dist/node/runtime/world/WorldOperationCoordinator.js +103 -2
- package/dist/node/runtime/world-revision/FileNativeWorldRevisionStore.js +696 -0
- package/dist/node/runtime/world-revision/WorldRevisionAuthoringTransaction.js +380 -0
- package/dist/node/runtime/world-revision/WorldRevisionSession.js +709 -0
- package/dist/node/runtime/world-revision/WorldRevisionWorkspace.js +494 -0
- package/dist/node/server/ConversationStream.js +109 -0
- package/dist/node/server/createServer.js +5 -1
- package/dist/node/shared/artifact-payload-contract.js +123 -0
- package/dist/node/shared/default-play-prompts.js +25 -45
- package/dist/node/shared/default-preset-host.js +114 -138
- package/dist/node/shared/default-setting-improvement-prompt.js +52 -38
- package/dist/node/shared/display-regex.js +114 -0
- package/dist/node/shared/first-party-action-choices.js +1 -6
- package/dist/node/shared/first-party-player-view.js +1 -6
- package/dist/node/shared/ordered-author-prompts.js +64 -0
- package/dist/node/shared/ordered-followups.js +42 -0
- package/dist/node/shared/ordered-play-prompts.js +73 -0
- package/dist/web/assets/index-BXfelCi9.js +1207 -0
- package/dist/web/assets/index-BYnhUxlk.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/node/runtime/model/SettingAuthorStream.js +0 -21
- package/dist/node/runtime/setting/DocumentCandidateSettingImprovement.js +0 -1731
- package/dist/web/assets/index-D5VqDvjY.js +0 -1192
- package/dist/web/assets/index-Xa0s35CJ.css +0 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { open, readFile, rename, rm } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { requestControlKey } from "../../protocol/worldExtensions.js";
|
|
5
|
+
import { builtinFollowupExample, defaultFollowupItems, } from "../../shared/ordered-followups.js";
|
|
6
|
+
import { readPackageFollowups } from "../content/PackageFollowups.js";
|
|
7
|
+
const fileName = "extension-controls.json";
|
|
8
|
+
/** Caller serializes mutations with the existing world lock; no Authority facts are changed. */
|
|
9
|
+
export class WorldExtensionControls {
|
|
10
|
+
static async read(root) {
|
|
11
|
+
try {
|
|
12
|
+
const state = JSON.parse(await readFile(join(root, fileName), "utf8"));
|
|
13
|
+
if (!isState(state))
|
|
14
|
+
throw new Error("Invalid world extension controls");
|
|
15
|
+
return state;
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
19
|
+
return { schemaVersion: 1, revision: 0, entries: {} };
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
static async write(root, state) {
|
|
24
|
+
const path = join(root, fileName);
|
|
25
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
26
|
+
try {
|
|
27
|
+
const file = await open(temporary, "wx", 0o600);
|
|
28
|
+
try {
|
|
29
|
+
await file.writeFile(JSON.stringify(state));
|
|
30
|
+
await file.sync();
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await file.close();
|
|
34
|
+
}
|
|
35
|
+
await rename(temporary, path);
|
|
36
|
+
const directory = await open(root, "r");
|
|
37
|
+
try {
|
|
38
|
+
await directory.sync();
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
await directory.close();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
await rm(temporary, { force: true });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
static async copy(sourceRoot, targetRoot) {
|
|
49
|
+
await this.write(targetRoot, await this.read(sourceRoot));
|
|
50
|
+
}
|
|
51
|
+
static async resolve(root, definitions, _presetId, change) {
|
|
52
|
+
const state = await this.read(root);
|
|
53
|
+
const before = JSON.stringify(state.entries);
|
|
54
|
+
for (const definition of definitions)
|
|
55
|
+
if (!Object.hasOwn(state.entries, definition.key)) {
|
|
56
|
+
const group = definitions.find((item) => item.key === definition.group);
|
|
57
|
+
const enabled = definition.defaultEnabled &&
|
|
58
|
+
(group === undefined ||
|
|
59
|
+
(state.entries[group.key]?.override ?? group.defaultEnabled));
|
|
60
|
+
state.entries[definition.key] = {
|
|
61
|
+
generation: enabled ? 0 : 1,
|
|
62
|
+
// Defaults select the next run; only world commands revoke frozen runs.
|
|
63
|
+
enabled: group === undefined || state.entries[group.key]?.enabled !== false,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (change) {
|
|
67
|
+
if (!definitions.some((item) => item.key === change.key))
|
|
68
|
+
throw new Error("The extension definition no longer exists");
|
|
69
|
+
const entry = state.entries[change.key] ?? {
|
|
70
|
+
generation: 0,
|
|
71
|
+
enabled: false,
|
|
72
|
+
};
|
|
73
|
+
if (change.value === "default")
|
|
74
|
+
delete entry.override;
|
|
75
|
+
else
|
|
76
|
+
entry.override = change.value === "on";
|
|
77
|
+
state.entries[change.key] = entry;
|
|
78
|
+
}
|
|
79
|
+
const selected = (definition) => state.entries[definition.key]?.override ?? definition.defaultEnabled;
|
|
80
|
+
const items = definitions.map((definition) => {
|
|
81
|
+
const group = definitions.find((item) => item.key === definition.group);
|
|
82
|
+
const enabled = selected(definition) && (group === undefined || selected(group));
|
|
83
|
+
const previous = state.entries[definition.key];
|
|
84
|
+
const affected = change !== undefined &&
|
|
85
|
+
(definition.key === change.key || definition.group === change.key);
|
|
86
|
+
const gateEnabled = affected
|
|
87
|
+
? enabled
|
|
88
|
+
: enabled || (previous?.enabled ?? true);
|
|
89
|
+
const entry = {
|
|
90
|
+
generation: (previous?.generation ?? 0) +
|
|
91
|
+
(previous?.enabled === true && !gateEnabled ? 1 : 0),
|
|
92
|
+
enabled: gateEnabled,
|
|
93
|
+
...(previous?.override === undefined
|
|
94
|
+
? {}
|
|
95
|
+
: { override: previous.override }),
|
|
96
|
+
};
|
|
97
|
+
state.entries[definition.key] = entry;
|
|
98
|
+
return {
|
|
99
|
+
...definition,
|
|
100
|
+
selected: selected(definition),
|
|
101
|
+
enabled,
|
|
102
|
+
overridden: entry.override !== undefined,
|
|
103
|
+
generation: entry.generation,
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
// Removing a source definition also belongs to the next run. Retain its
|
|
107
|
+
// frozen generation; an explicit package-group close still revokes all children.
|
|
108
|
+
if (change?.key === "group:package" &&
|
|
109
|
+
state.entries[change.key]?.enabled === false)
|
|
110
|
+
for (const [key, entry] of Object.entries(state.entries))
|
|
111
|
+
if (key.startsWith("package:") && entry.enabled) {
|
|
112
|
+
entry.enabled = false;
|
|
113
|
+
entry.generation++;
|
|
114
|
+
}
|
|
115
|
+
if (before !== JSON.stringify(state.entries)) {
|
|
116
|
+
state.revision++;
|
|
117
|
+
await this.write(root, state);
|
|
118
|
+
}
|
|
119
|
+
return { revision: state.revision, items };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function extensionDefinitions(binding, files, views, locale) {
|
|
123
|
+
const items = [];
|
|
124
|
+
for (const item of binding.definition.followupItems ??
|
|
125
|
+
defaultFollowupItems(binding.definition.followups)) {
|
|
126
|
+
const group = item.kind === "content-package";
|
|
127
|
+
const request = binding.definition.followups.find((def) => def.id === item.id);
|
|
128
|
+
items.push({
|
|
129
|
+
key: group ? "group:package" : requestControlKey(binding.id, item.id),
|
|
130
|
+
id: item.id,
|
|
131
|
+
name: group
|
|
132
|
+
? locale === "zh-CN"
|
|
133
|
+
? "内容包后置请求"
|
|
134
|
+
: "Content package requests"
|
|
135
|
+
: item.kind === "builtin"
|
|
136
|
+
? builtinFollowupExample(locale).definition.displayName
|
|
137
|
+
: request.displayName,
|
|
138
|
+
kind: group ? "group" : "request",
|
|
139
|
+
source: group
|
|
140
|
+
? "package"
|
|
141
|
+
: item.kind === "builtin"
|
|
142
|
+
? "builtin"
|
|
143
|
+
: "preset",
|
|
144
|
+
defaultEnabled: item.enabled,
|
|
145
|
+
});
|
|
146
|
+
if (group)
|
|
147
|
+
for (const child of readPackageFollowups(files).followups)
|
|
148
|
+
items.push({
|
|
149
|
+
key: `package:${child.definition.id}`,
|
|
150
|
+
id: `package:${child.definition.id}`,
|
|
151
|
+
name: child.definition.displayName,
|
|
152
|
+
kind: "request",
|
|
153
|
+
source: "package",
|
|
154
|
+
group: "group:package",
|
|
155
|
+
defaultEnabled: child.enabled,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
for (const panel of binding.definition.playerViewPanels)
|
|
159
|
+
items.push({
|
|
160
|
+
key: `preset:${binding.id}:panel:${panel.id}`,
|
|
161
|
+
id: panel.id,
|
|
162
|
+
name: panel.config.title ??
|
|
163
|
+
views.find((view) => view.id === panel.source.view)?.title ??
|
|
164
|
+
panel.source.view,
|
|
165
|
+
kind: "panel",
|
|
166
|
+
source: "preset",
|
|
167
|
+
defaultEnabled: true,
|
|
168
|
+
});
|
|
169
|
+
const covered = new Set(binding.definition.playerViewPanels.map((panel) => panel.source.view));
|
|
170
|
+
for (const view of views)
|
|
171
|
+
if (!covered.has(view.id))
|
|
172
|
+
items.push({
|
|
173
|
+
key: `view:${view.id}`,
|
|
174
|
+
id: view.id,
|
|
175
|
+
name: view.title,
|
|
176
|
+
kind: "view",
|
|
177
|
+
source: "world",
|
|
178
|
+
defaultEnabled: true,
|
|
179
|
+
});
|
|
180
|
+
return items;
|
|
181
|
+
}
|
|
182
|
+
function isState(value) {
|
|
183
|
+
if (typeof value !== "object" ||
|
|
184
|
+
value === null ||
|
|
185
|
+
!("schemaVersion" in value) ||
|
|
186
|
+
value.schemaVersion !== 1 ||
|
|
187
|
+
!("revision" in value) ||
|
|
188
|
+
!Number.isSafeInteger(value.revision) ||
|
|
189
|
+
Number(value.revision) < 0 ||
|
|
190
|
+
!("entries" in value) ||
|
|
191
|
+
typeof value.entries !== "object" ||
|
|
192
|
+
value.entries === null ||
|
|
193
|
+
Array.isArray(value.entries) ||
|
|
194
|
+
Object.keys(value).length !== 3)
|
|
195
|
+
return false;
|
|
196
|
+
return Object.values(value.entries).every((entry) => typeof entry === "object" &&
|
|
197
|
+
entry !== null &&
|
|
198
|
+
"generation" in entry &&
|
|
199
|
+
Number.isSafeInteger(entry.generation) &&
|
|
200
|
+
Number(entry.generation) >= 0 &&
|
|
201
|
+
"enabled" in entry &&
|
|
202
|
+
typeof entry.enabled === "boolean" &&
|
|
203
|
+
(!("override" in entry) || typeof entry.override === "boolean") &&
|
|
204
|
+
Object.keys(entry).every((key) => ["generation", "enabled", "override"].includes(key)));
|
|
205
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { requestControlKey, } from "../../protocol/worldExtensions.js";
|
|
3
|
+
import { WorldExtensionControls } from "./WorldExtensionControls.js";
|
|
4
|
+
/** Cancellation is best effort; persisted generations remain the visibility authority. */
|
|
5
|
+
export class WorldExtensionRequests {
|
|
6
|
+
#root;
|
|
7
|
+
#active = new Set();
|
|
8
|
+
constructor(worldsRoot) {
|
|
9
|
+
this.#root = worldsRoot;
|
|
10
|
+
}
|
|
11
|
+
async visible(worldId, record) {
|
|
12
|
+
const control = record.extensionControl ?? {
|
|
13
|
+
key: requestControlKey(record.playPresetId, record.requestId),
|
|
14
|
+
generation: 0,
|
|
15
|
+
};
|
|
16
|
+
const state = await WorldExtensionControls.read(join(this.#root, worldId));
|
|
17
|
+
const current = state.entries[control.key];
|
|
18
|
+
return current === undefined
|
|
19
|
+
? control.generation === 0
|
|
20
|
+
: current.enabled && current.generation === control.generation;
|
|
21
|
+
}
|
|
22
|
+
async changed(worldId) {
|
|
23
|
+
for (const active of this.#active) {
|
|
24
|
+
if (active.worldId !== worldId)
|
|
25
|
+
continue;
|
|
26
|
+
if (!(await this.visible(worldId, {
|
|
27
|
+
playPresetId: "",
|
|
28
|
+
requestId: "",
|
|
29
|
+
extensionControl: active.control,
|
|
30
|
+
})))
|
|
31
|
+
active.controller.abort();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async acquire(worldId, record, signal) {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const entry = {
|
|
37
|
+
worldId,
|
|
38
|
+
control: record.extensionControl ?? {
|
|
39
|
+
key: requestControlKey(record.playPresetId, record.requestId),
|
|
40
|
+
generation: 0,
|
|
41
|
+
},
|
|
42
|
+
controller,
|
|
43
|
+
};
|
|
44
|
+
this.#active.add(entry);
|
|
45
|
+
// Register before reading, so a concurrent accepted change cannot slip between
|
|
46
|
+
// the persisted check and dispatch registration.
|
|
47
|
+
try {
|
|
48
|
+
if (!(await this.visible(worldId, record)))
|
|
49
|
+
controller.abort();
|
|
50
|
+
return {
|
|
51
|
+
signal: signal === undefined
|
|
52
|
+
? controller.signal
|
|
53
|
+
: AbortSignal.any([signal, controller.signal]),
|
|
54
|
+
release: () => {
|
|
55
|
+
this.#active.delete(entry);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
this.#active.delete(entry);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|