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
@@ -16,8 +16,8 @@ export async function aggregateChatModelStream(body, onDelta) {
16
16
  }
17
17
  const payload = streamRecord(event.data);
18
18
  sawPayload = true;
19
- if (isRecord(payload.error))
20
- throw new ModelHostFailureError("Provider SSE returned an explicit error");
19
+ if (isPresent(payload.error))
20
+ throw providerSseFailure("chat_completions", "Chat Completions", event.event ?? "error", payload, payload.error);
21
21
  if (!Array.isArray(payload.choices))
22
22
  throw new Error("Chat SSE choices are invalid");
23
23
  if (payload.choices.length > 1)
@@ -280,7 +280,7 @@ export async function aggregateAnthropicModelStream(body, onDelta) {
280
280
  case "ping":
281
281
  break;
282
282
  case "error":
283
- throw new ModelHostFailureError("Anthropic SSE returned an explicit error");
283
+ throw providerSseFailure("anthropic_messages", "Anthropic", payload.type, payload, payload.error);
284
284
  default:
285
285
  // Anthropic may add top-level event types. Unknown events do not alter
286
286
  // the content blocks that form the final continuation.
@@ -388,15 +388,47 @@ function parseStreamJson(source) {
388
388
  throw new Error("Provider SSE data is not valid JSON");
389
389
  }
390
390
  }
391
+ function providerSseFailure(provider, label, eventType, payload, errorValue) {
392
+ const error = isRecord(errorValue) ? errorValue : {};
393
+ const type = boundedNonEmptyString(error.type, 256);
394
+ const code = boundedStringOrNumber(error.code, 256);
395
+ const message = boundedNonEmptyString(error.message, 4096) ??
396
+ boundedNonEmptyString(payload.message, 4096) ??
397
+ boundedStringOrNumber(errorValue, 4096);
398
+ const requestId = boundedNonEmptyString(payload.request_id, 256) ??
399
+ boundedNonEmptyString(error.request_id, 256);
400
+ const identity = [...new Set([type, code].filter(isDefined))].join("/");
401
+ const summary = identity !== "" && message !== undefined
402
+ ? `${identity}: ${message}`
403
+ : identity !== ""
404
+ ? identity
405
+ : message;
406
+ const details = {
407
+ provider,
408
+ eventType,
409
+ ...(type === undefined ? {} : { type }),
410
+ ...(code === undefined ? {} : { code }),
411
+ ...(message === undefined ? {} : { message }),
412
+ ...(requestId === undefined ? {} : { requestId }),
413
+ };
414
+ const requestSuffix = requestId === undefined ? "" : ` (request_id: ${requestId})`;
415
+ return new ModelHostFailureError(summary === undefined
416
+ ? `${label} SSE returned an explicit error${requestSuffix}`
417
+ : `${label} SSE error: ${summary}${requestSuffix}`, { details });
418
+ }
391
419
  function streamIndex(value) {
392
420
  if (!Number.isSafeInteger(value) || value < 0)
393
421
  throw new Error("Provider SSE content index is invalid");
394
422
  return value;
395
423
  }
396
424
  function appendBlockString(block, field, delta, expectedType) {
397
- if (block.type !== expectedType || typeof block[field] !== "string")
425
+ // Some streams introduce the signature only in signature_delta. Retain
426
+ // exactly that returned value; do not require an empty start placeholder.
427
+ const firstSignature = field === "signature" && block[field] === undefined;
428
+ if (block.type !== expectedType ||
429
+ (typeof block[field] !== "string" && !firstSignature))
398
430
  throw new Error("Anthropic SSE content block does not match its delta");
399
- block[field] += delta;
431
+ block[field] = firstSignature ? delta : String(block[field]) + delta;
400
432
  }
401
433
  function mergeUsage(target, value) {
402
434
  if (!isRecord(value))
@@ -425,6 +457,20 @@ function mergeUsage(target, value) {
425
457
  function stringOrUndefined(value) {
426
458
  return typeof value === "string" ? value : undefined;
427
459
  }
460
+ function boundedNonEmptyString(value, maximumLength) {
461
+ if (typeof value !== "string")
462
+ return undefined;
463
+ const trimmed = value.trim();
464
+ return trimmed === "" ? undefined : trimmed.slice(0, maximumLength);
465
+ }
466
+ function boundedStringOrNumber(value, maximumLength) {
467
+ if (typeof value === "number" && Number.isFinite(value))
468
+ return String(value).slice(0, maximumLength);
469
+ return boundedNonEmptyString(value, maximumLength);
470
+ }
471
+ function isDefined(value) {
472
+ return value !== undefined;
473
+ }
428
474
  function isPresent(value) {
429
475
  return value !== undefined && value !== null;
430
476
  }
@@ -1,3 +1,4 @@
1
+ import { readDeclaredWorldClock } from "../prompt/WorldMaintenanceReport.js";
1
2
  import { createHash, randomUUID } from "node:crypto";
2
3
  import { FileNativePromptCompiler, } from "../prompt/FileNativePromptCompiler.js";
3
4
  import { validateMaterialList } from "../prompt/MaterialSelection.js";
@@ -68,28 +69,41 @@ export class FileNativeContinuityCorrection {
68
69
  .catch(() => undefined);
69
70
  }, claimHeartbeatIntervalMilliseconds);
70
71
  claimHeartbeat.unref();
71
- const candidate = {
72
- ...revision,
73
- id: `correction-${randomUUID()}`,
74
- operationId: input.operationId,
75
- worldId: input.worldId,
76
- parentHead: binding.parentHead,
77
- mode: input.mode,
78
- version: 1,
79
- materials: structuredClone(binding.additionalMaterials),
80
- originalMaterials: structuredClone(binding.additionalMaterials),
81
- history: structuredClone(binding.history),
82
- reads: new Map(),
83
- previewedVersion: null,
84
- stateOperationClaim: claimed.handle,
85
- claimHeartbeat,
86
- };
87
- this.#candidates.set(candidate.id, candidate);
88
- return {
89
- candidateId: candidate.id,
90
- version: candidate.version,
91
- parentHead: candidate.parentHead,
92
- };
72
+ try {
73
+ const candidate = {
74
+ ...revision,
75
+ ...(await this.#worlds.inspectDocumentMaintenance(input.worldId, binding.parentHead)),
76
+ narrativeCheckpoint: binding.narrativeCheckpoint,
77
+ id: `correction-${randomUUID()}`,
78
+ operationId: input.operationId,
79
+ worldId: input.worldId,
80
+ parentHead: binding.parentHead,
81
+ mode: input.mode,
82
+ version: 1,
83
+ materials: structuredClone(binding.additionalMaterials),
84
+ originalMaterials: structuredClone(binding.additionalMaterials),
85
+ history: structuredClone(binding.history),
86
+ reads: new Map(),
87
+ previewedVersion: null,
88
+ stateOperationClaim: claimed.handle,
89
+ claimHeartbeat,
90
+ };
91
+ this.#candidates.set(candidate.id, candidate);
92
+ return {
93
+ candidateId: candidate.id,
94
+ version: candidate.version,
95
+ parentHead: candidate.parentHead,
96
+ };
97
+ }
98
+ catch (error) {
99
+ clearInterval(claimHeartbeat);
100
+ this.#worlds.releaseControl(input.worldId, input.operationId);
101
+ await Promise.allSettled([
102
+ this.#worlds.releaseOperationReservation(input.operationId),
103
+ this.#worlds.operations.releaseCorrectionWorld(claimed.handle),
104
+ ]);
105
+ throw error;
106
+ }
93
107
  }
94
108
  readDocument(candidateId, handle) {
95
109
  const candidate = this.#candidate(candidateId);
@@ -173,7 +187,9 @@ export class FileNativeContinuityCorrection {
173
187
  if (candidate.snapshot.status !== "usable")
174
188
  throw new Error("Only a usable revision can commit a correction");
175
189
  try {
190
+ const worldClock = readDeclaredWorldClock(candidate.snapshot);
176
191
  return await this.#worlds.commitCorrection({
192
+ ...(worldClock === undefined ? {} : { worldClock }),
177
193
  operationId: candidate.operationId,
178
194
  worldId: candidate.worldId,
179
195
  parentHead: candidate.parentHead,
@@ -220,11 +236,14 @@ export class FileNativeContinuityCorrection {
220
236
  documentSnapshot: candidate.snapshot,
221
237
  additionalMaterials: materials,
222
238
  history: candidate.history,
239
+ documentMaintenance: candidate.documentMaintenance,
240
+ documentMaintenanceUnavailableReason: candidate.documentMaintenanceUnavailableReason,
241
+ narrativeCheckpoint: candidate.narrativeCheckpoint,
223
242
  },
224
- playerInputPlacement: "bootstrap",
243
+ playerInputPlacement: "append",
225
244
  playerInput: "",
226
245
  modelBinding: prompt.modelBinding,
227
- });
246
+ }, prompt.playPreset);
228
247
  }
229
248
  #candidate(id) {
230
249
  const candidate = this.#candidates.get(id);
@@ -267,27 +286,18 @@ function readCompleteDocument(snapshot, handle) {
267
286
  ? [{ shortRef: requested }]
268
287
  : [{ documentId: requested }, { shortRef: requested }];
269
288
  for (const selector of selectors) {
270
- let cursor = null;
271
- let descriptor = null;
272
- do {
273
- const result = snapshot.query({
274
- kind: "read_document",
275
- document: selector,
276
- maxBytes: 65_536,
277
- cursor,
278
- });
279
- if (result.kind === "error") {
280
- if (result.diagnostics.every(({ code }) => code === "document_not_found"))
281
- break;
282
- throw new Error(worldDocumentRevisionFailureMessage(result.diagnostics));
283
- }
284
- if (result.kind !== "read_document")
285
- throw new Error("The correction document's exact read returned the wrong query result");
286
- descriptor = result.document;
287
- cursor = result.page.nextCursor;
288
- } while (cursor !== null);
289
- if (descriptor !== null)
290
- return descriptor;
289
+ const result = snapshot.query({
290
+ kind: "read_document",
291
+ document: selector,
292
+ });
293
+ if (result.kind === "error") {
294
+ if (result.diagnostics.every(({ code }) => code === "document_not_found"))
295
+ continue;
296
+ throw new Error(worldDocumentRevisionFailureMessage(result.diagnostics));
297
+ }
298
+ if (result.kind !== "read_document")
299
+ throw new Error("The correction document's exact read returned the wrong query result");
300
+ return result.document;
291
301
  }
292
302
  throw new Error(`Correction document ${handle} does not exist`);
293
303
  }