arcane-os 0.3.1 → 0.3.2

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 (153) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +86 -117
  3. package/bin/arcane-test.mjs +170 -46
  4. package/browser-runtime/ai/browser-speech-artifacts.mjs +855 -895
  5. package/browser-runtime/ai/browser-speech-providers.mjs +80 -204
  6. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
  7. package/browser-runtime/ai/browser-wasm.mjs +24 -35
  8. package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
  9. package/browser-runtime/ai/model-controller.mjs +584 -181
  10. package/browser-runtime/ai/speech-worker-client.mjs +8 -148
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +642 -374
  12. package/browser-runtime/dom-event-instrumentation.mjs +55 -147
  13. package/browser-runtime/event-manager.mjs +239 -624
  14. package/package.json +5 -6
  15. package/runtime/arcane/components/app-bar.html +3 -15
  16. package/runtime/arcane/components/assistant-panel.html +10 -10
  17. package/runtime/arcane/components/calculator.html +1 -1
  18. package/runtime/arcane/components/chat.html +1359 -135
  19. package/runtime/arcane/components/conversation-view.html +2 -2
  20. package/runtime/arcane/components/document-inspector.html +11 -17
  21. package/runtime/arcane/components/file-manager.html +13 -56
  22. package/runtime/arcane/components/markdown-document.html +82 -281
  23. package/runtime/arcane/components/markdown-editor.html +7 -10
  24. package/runtime/arcane/components/media-embed.html +6 -6
  25. package/runtime/arcane/components/screen-capture.html +4 -4
  26. package/runtime/arcane/components/source-explanation.html +2 -2
  27. package/runtime/arcane/components/speech.html +112 -68
  28. package/runtime/arcane/components/terminal-workspace.html +4 -4
  29. package/runtime/arcane/components/theme-editor.html +1 -1
  30. package/runtime/arcane/components/unified-inbox.html +2 -2
  31. package/runtime/arcane/components/voice-transcription.html +31 -21
  32. package/runtime/arcane/entities/Calculation.js +2 -3
  33. package/runtime/arcane/entities/Chat.js +228 -43
  34. package/runtime/arcane/entities/Preference.js +3 -5
  35. package/runtime/arcane/entities/Weather.js +5 -5
  36. package/runtime/arcane/modules/AI.js +1042 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +618 -359
  38. package/runtime/arcane/modules/AIResponseLength.js +9 -19
  39. package/runtime/arcane/modules/AIRuntimeState.js +109 -72
  40. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
  41. package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
  42. package/runtime/arcane/modules/CalculatorEngine.js +9 -9
  43. package/runtime/arcane/modules/CommunicationAppController.js +3 -7
  44. package/runtime/arcane/modules/ComponentContracts.js +30 -32
  45. package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
  46. package/runtime/arcane/modules/ConversationActionItems.js +26 -59
  47. package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
  48. package/runtime/arcane/modules/ConversationTimebox.js +27 -15
  49. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
  50. package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
  51. package/runtime/arcane/modules/HTMLImport.js +54 -1
  52. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
  53. package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
  54. package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
  55. package/runtime/arcane/modules/MD.js +1 -45
  56. package/runtime/arcane/modules/Mail.js +51 -103
  57. package/runtime/arcane/modules/MailOutbox.mjs +95 -193
  58. package/runtime/arcane/modules/MailTransport.mjs +36 -57
  59. package/runtime/arcane/modules/ModelDefinition.js +22 -106
  60. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
  61. package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
  62. package/runtime/arcane/modules/PreferenceStore.js +102 -30
  63. package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
  64. package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
  65. package/runtime/arcane/modules/ScreenCapture.js +175 -128
  66. package/runtime/arcane/modules/SpeechPlayback.js +46 -149
  67. package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
  68. package/runtime/arcane/modules/ToolCallRouter.js +25 -12
  69. package/runtime/arcane/modules/YouTubeMedia.js +6 -5
  70. package/schemas/arcane-app-bundle.schema.json +13 -78
  71. package/schemas/arcane-app.schema.json +9 -25
  72. package/schemas/arcane-lock.schema.json +18 -151
  73. package/schemas/arcane-package.schema.json +2 -16
  74. package/schemas/native-build-plan.schema.json +119 -122
  75. package/src/app-descriptor.mjs +75 -132
  76. package/src/application-tests.mjs +200 -0
  77. package/src/cli/main.mjs +27 -46
  78. package/src/constants.mjs +3 -4
  79. package/src/dev-server.mjs +30 -324
  80. package/src/doctor.mjs +92 -154
  81. package/src/dom-event-instrumentation.mjs +55 -147
  82. package/src/errors.mjs +2 -3
  83. package/src/event-manager.mjs +239 -624
  84. package/src/event-queue.mjs +3 -3
  85. package/src/import-map.mjs +273 -1028
  86. package/src/index.mjs +14 -16
  87. package/src/installed-sdk-runtime.mjs +27 -67
  88. package/src/integrated-provider-loader.mjs +53 -382
  89. package/src/mail-api.mjs +0 -2
  90. package/src/mail-server.mjs +224 -580
  91. package/src/mail.mjs +4 -10
  92. package/src/native-plan.mjs +163 -598
  93. package/src/native-provider-loader.mjs +104 -1063
  94. package/src/packager/core.mjs +485 -3229
  95. package/src/process.mjs +5 -10
  96. package/src/release-bundle.mjs +292 -2405
  97. package/src/runtime.mjs +76 -396
  98. package/src/scaffold.mjs +30 -80
  99. package/src/sdk-browser-runtime.mjs +70 -626
  100. package/src/source-server.mjs +588 -0
  101. package/src/targets/index.mjs +78 -188
  102. package/src/templates/workspace-template.mjs +19 -135
  103. package/src/testing-loader.mjs +164 -0
  104. package/src/testing.mjs +1 -1
  105. package/src/toolchain.mjs +131 -544
  106. package/src/update-check.mjs +26 -64
  107. package/src/workspace-operation-lock.mjs +139 -430
  108. package/src/workspace-runtime.mjs +109 -1558
  109. package/src/workspace.mjs +40 -302
  110. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
  111. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
  112. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
  113. package/browser-runtime/ai/internal/sha256.mjs +0 -166
  114. package/docs/architecture.md +0 -344
  115. package/docs/compatibility.md +0 -36
  116. package/docs/event-manager.md +0 -294
  117. package/docs/platform-targets.md +0 -108
  118. package/docs/publishing.md +0 -201
  119. package/docs/reference/README.md +0 -185
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1295
  122. package/docs/reference/ai/browser-wasm.md +0 -530
  123. package/docs/reference/arcane-ollama.md +0 -288
  124. package/docs/reference/availability-and-normalization.md +0 -183
  125. package/docs/reference/behavioral-testing.md +0 -133
  126. package/docs/reference/cli.md +0 -779
  127. package/docs/reference/core/README.md +0 -62
  128. package/docs/reference/core/arcane-ai-contracts.md +0 -907
  129. package/docs/reference/core/arcane-api.md +0 -601
  130. package/docs/reference/core/arcane-entities.md +0 -65
  131. package/docs/reference/core/arcane-events.md +0 -134
  132. package/docs/reference/core/ollama-module.md +0 -181
  133. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
  134. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
  135. package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
  136. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
  137. package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
  138. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
  139. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
  140. package/docs/reference/event-manager.md +0 -1511
  141. package/docs/reference/inventory/package-api.json +0 -3284
  142. package/docs/reference/inventory/runtime-components.json +0 -1011
  143. package/docs/reference/inventory/runtime-entities.json +0 -26
  144. package/docs/reference/inventory/runtime-modules.json +0 -1431
  145. package/docs/reference/mail.md +0 -316
  146. package/docs/reference/protocols.md +0 -719
  147. package/docs/reference/runtime-components.md +0 -1366
  148. package/docs/reference/runtime-entities.md +0 -303
  149. package/docs/reference/runtime-modules.md +0 -2965
  150. package/docs/reference/sdk-api.md +0 -6698
  151. package/docs/roadmap.md +0 -79
  152. package/docs/work-amplification.md +0 -129
  153. package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
@@ -1,28 +1,20 @@
1
1
  export const SPEECH_WORKER_PROTOCOL = "arcane-ai-speech-worker/1";
2
2
 
3
+ const completeValue = (value) => value;
4
+
3
5
  const SPEECH_WORKER_ERROR_PROTOCOL = "arcane-ai-speech-worker-error/1";
4
6
 
5
7
  const ARTIFACT_GRAPH_MODULE_GRAPH =
6
8
  "browser-speech-authenticated-artifact-graph";
7
9
  const GRAPH_GUARD_NAME = "__arcaneBrowserSpeechArtifactGraphGuardsV1";
10
+ const MODULE_ROUTER_NAME = "__arcaneBrowserSpeechModuleRouterV1";
8
11
  const NESTED_WORKER_PROTOCOL =
9
12
  "arcane-ai-browser-speech-artifact-module-worker/1";
10
- const GRAPH_ADMISSIONS = new Set([
11
- "artifact-graph-network-dbopfs-verified",
12
- "artifact-graph-dbopfs-cache-verified",
13
- "artifact-graph-offline-dbopfs-cache-verified",
14
- "artifact-graph-network-dbopfs-partially-checked",
15
- "artifact-graph-dbopfs-cache-partially-checked",
16
- "artifact-graph-offline-dbopfs-cache-partially-checked",
17
- "artifact-graph-network-dbopfs-unchecked",
18
- "artifact-graph-dbopfs-cache-unchecked",
19
- "artifact-graph-offline-dbopfs-cache-unchecked",
20
- ]);
21
- const ADAPTERS = Object.freeze({
13
+ const ADAPTERS = completeValue({
22
14
  stt: "transformers-whisper",
23
15
  tts: "kokoro-js",
24
16
  });
25
- const ONNX_NAMESPACES = Object.freeze({
17
+ const ONNX_NAMESPACES = completeValue({
26
18
  stt: "transformers-env-backends-onnx-wasm",
27
19
  tts: "kokoro-env-wasm-paths",
28
20
  });
@@ -30,7 +22,7 @@ const ARTIFACT_GRAPH_TRANSFORM_KINDS = new Set([
30
22
  "function-return-this-to-global-this",
31
23
  "typed-array-constructor",
32
24
  ]);
33
- const PUBLIC_WORKER_OPERATIONS = Object.freeze([
25
+ const PUBLIC_WORKER_OPERATIONS = completeValue([
34
26
  "load",
35
27
  "use",
36
28
  "status",
@@ -41,16 +33,16 @@ const TRANSPORT_WORKER_OPERATION_SET = new Set([
41
33
  ...PUBLIC_WORKER_OPERATIONS,
42
34
  "cancel",
43
35
  ]);
44
- const BOTH_WORKER_ROLES = Object.freeze(["stt", "tts"]);
45
- const LOAD_OPERATION = Object.freeze(["load"]);
46
- const USE_OPERATION = Object.freeze(["use"]);
47
- const STATUS_OPERATION = Object.freeze(["status"]);
48
- const UNLOAD_OPERATION = Object.freeze(["unload"]);
49
- const DISPOSE_OPERATION = Object.freeze(["dispose"]);
50
- const UNLOAD_OR_DISPOSE_OPERATIONS = Object.freeze(["unload", "dispose"]);
51
- const LOAD_OR_USE_OPERATIONS = Object.freeze(["load", "use"]);
36
+ const BOTH_WORKER_ROLES = completeValue(["stt", "tts"]);
37
+ const LOAD_OPERATION = completeValue(["load"]);
38
+ const USE_OPERATION = completeValue(["use"]);
39
+ const STATUS_OPERATION = completeValue(["status"]);
40
+ const UNLOAD_OPERATION = completeValue(["unload"]);
41
+ const DISPOSE_OPERATION = completeValue(["dispose"]);
42
+ const UNLOAD_OR_DISPOSE_OPERATIONS = completeValue(["unload", "dispose"]);
43
+ const LOAD_OR_USE_OPERATIONS = completeValue(["load", "use"]);
52
44
  const SDK_WORKER_ERRORS = new WeakSet();
53
- const WORKER_ERROR_MESSAGES = Object.freeze({
45
+ const WORKER_ERROR_MESSAGES = completeValue({
54
46
  ARCANE_AI_REQUEST_ABORTED: "The speech worker operation was cancelled.",
55
47
  ARCANE_AI_NOT_READY: "The speech worker is not loaded.",
56
48
  ARCANE_AI_INVALID_REQUEST: "The speech worker request was rejected.",
@@ -77,10 +69,10 @@ const WORKER_ERROR_MESSAGES = Object.freeze({
77
69
  const WORKER_ERROR_REASON_ADMISSIONS = new Map();
78
70
 
79
71
  function registerWorkerErrorReasons(code, roles, operations, reasons) {
80
- const admission = Object.freeze({
72
+ const admission = completeValue({
81
73
  code,
82
- roles: Object.freeze([...roles]),
83
- operations: Object.freeze([...operations]),
74
+ roles: completeValue([...roles]),
75
+ operations: completeValue([...operations]),
84
76
  });
85
77
  for (const reason of reasons) WORKER_ERROR_REASON_ADMISSIONS.set(reason, admission);
86
78
  }
@@ -183,7 +175,7 @@ registerWorkerErrorReasons("ARCANE_AI_INVALID_REQUEST", ["tts"], LOAD_OPERATION,
183
175
  "tts-default-voice-empty",
184
176
  ]);
185
177
  registerWorkerErrorReasons("ARCANE_AI_INVALID_REQUEST", ["tts"], USE_OPERATION, [
186
- "tts-synthesis-speed-out-of-range",
178
+ "tts-synthesis-speed-not-positive",
187
179
  "tts-synthesis-text-empty",
188
180
  "tts-synthesis-voice-empty",
189
181
  "tts-synthesis-voice-not-declared",
@@ -465,7 +457,11 @@ function workerError(code, message, cause, reason) {
465
457
  }
466
458
 
467
459
  function isSdkWorkerError(value) {
468
- return value instanceof Error && SDK_WORKER_ERRORS.has(value);
460
+ try {
461
+ return value instanceof Error && SDK_WORKER_ERRORS.has(value);
462
+ } catch {
463
+ return false;
464
+ }
469
465
  }
470
466
 
471
467
  function admitWorkerFailure(error, code, message, reason) {
@@ -518,20 +514,237 @@ export function collectSpeechTransferables(value) {
518
514
  }
519
515
 
520
516
  function serializedError(error, role, op) {
521
- const admission = isSdkWorkerError(error)
522
- ? workerErrorReasonAdmission(error.reason, role, op)
517
+ const sdkError = isSdkWorkerError(error);
518
+ let reportedCode;
519
+ let reportedMessage;
520
+ let reportedReason;
521
+ let reportedCause;
522
+ try { reportedCode = Reflect.get(error, "code"); } catch {}
523
+ try { reportedMessage = Reflect.get(error, "message"); } catch {}
524
+ try { reportedReason = Reflect.get(error, "reason"); } catch {}
525
+ if (sdkError) {
526
+ try { reportedCause = Reflect.get(error, "cause"); } catch (cause) {
527
+ reportedCause = cause;
528
+ }
529
+ } else {
530
+ reportedCause = error;
531
+ }
532
+ const admission = sdkError
533
+ ? workerErrorReasonAdmission(reportedReason, role, op)
523
534
  : null;
524
- const admittedCode = isSdkWorkerError(error)
525
- && Object.hasOwn(WORKER_ERROR_MESSAGES, error.code)
526
- && admission?.code === error.code;
527
- const code = admittedCode ? error.code : "ARCANE_AI_PROVIDER_REQUEST_FAILED";
528
- const reason = admittedCode ? error.reason : operationFailureReason(role, op);
529
- return Object.freeze({
535
+ const admittedCode = sdkError
536
+ && Object.hasOwn(WORKER_ERROR_MESSAGES, reportedCode)
537
+ && admission?.code === reportedCode;
538
+ const code = admittedCode ? reportedCode : "ARCANE_AI_PROVIDER_REQUEST_FAILED";
539
+ const reason = admittedCode ? reportedReason : operationFailureReason(role, op);
540
+ const message = typeof reportedMessage === "string" && reportedMessage.length > 0
541
+ ? reportedMessage
542
+ : WORKER_ERROR_MESSAGES[code];
543
+ const envelope = completeValue({
530
544
  protocol: SPEECH_WORKER_ERROR_PROTOCOL,
531
545
  code,
532
- message: WORKER_ERROR_MESSAGES[code],
546
+ message,
533
547
  reason,
534
548
  });
549
+ if (reportedCause !== undefined) {
550
+ envelope.cause = serializedDiagnosticValue(reportedCause);
551
+ }
552
+ return envelope;
553
+ }
554
+
555
+ function fallbackSerializedError(error, role, op) {
556
+ let message;
557
+ try { message = Reflect.get(error, "message"); } catch {}
558
+ return completeValue({
559
+ protocol: SPEECH_WORKER_ERROR_PROTOCOL,
560
+ code: "ARCANE_AI_PROVIDER_REQUEST_FAILED",
561
+ message: typeof message === "string" && message.length > 0
562
+ ? message
563
+ : WORKER_ERROR_MESSAGES.ARCANE_AI_PROVIDER_REQUEST_FAILED,
564
+ reason: operationFailureReason(role, op),
565
+ });
566
+ }
567
+
568
+ function sendSerializedError(send, response, error, role, op, consoleScope) {
569
+ try {
570
+ response.error = serializedError(error, role, op);
571
+ send(response, []);
572
+ } catch (transportError) {
573
+ try {
574
+ consoleScope?.console?.error?.(
575
+ "The speech Worker could not transport its complete failure diagnostic.",
576
+ error,
577
+ transportError,
578
+ );
579
+ } catch {}
580
+ response.error = fallbackSerializedError(error, role, op);
581
+ send(response, []);
582
+ }
583
+ }
584
+
585
+ function diagnosticText(value, fallback) {
586
+ try {
587
+ return String(value);
588
+ } catch {
589
+ return fallback;
590
+ }
591
+ }
592
+
593
+ function defineDiagnosticProperty(target, key, value) {
594
+ Object.defineProperty(target, key, {
595
+ configurable: true,
596
+ enumerable: true,
597
+ value,
598
+ writable: true,
599
+ });
600
+ }
601
+
602
+ function diagnosticType(value) {
603
+ try {
604
+ return Object.prototype.toString.call(value).slice(8, -1);
605
+ } catch {
606
+ return "UninspectableObject";
607
+ }
608
+ }
609
+
610
+ function serializedDiagnosticValue(value, seen = new WeakMap()) {
611
+ if (value === null || value === undefined) return value;
612
+ const type = typeof value;
613
+ if (type !== "object" && type !== "function") {
614
+ return type === "symbol"
615
+ ? diagnosticText(value, "[symbol could not be represented]")
616
+ : value;
617
+ }
618
+ if (seen.has(value)) return seen.get(value);
619
+
620
+ const result = Object.create(null);
621
+ seen.set(value, result);
622
+ let descriptors;
623
+ try {
624
+ descriptors = Object.getOwnPropertyDescriptors(value);
625
+ } catch (error) {
626
+ defineDiagnosticProperty(
627
+ result,
628
+ "inspectionError",
629
+ serializedDiagnosticValue(error, seen),
630
+ );
631
+ return result;
632
+ }
633
+
634
+ const symbolProperties = [];
635
+ for (const key of Reflect.ownKeys(descriptors)) {
636
+ const descriptor = descriptors[key];
637
+ const projected = Object.create(null);
638
+ if (Object.hasOwn(descriptor, "value")) {
639
+ defineDiagnosticProperty(
640
+ projected,
641
+ "value",
642
+ serializedDiagnosticValue(descriptor.value, seen),
643
+ );
644
+ } else {
645
+ defineDiagnosticProperty(projected, "kind", "accessor");
646
+ if (descriptor.get !== undefined) {
647
+ defineDiagnosticProperty(
648
+ projected,
649
+ "get",
650
+ diagnosticText(descriptor.get, "[getter could not be represented]"),
651
+ );
652
+ }
653
+ if (descriptor.set !== undefined) {
654
+ defineDiagnosticProperty(
655
+ projected,
656
+ "set",
657
+ diagnosticText(descriptor.set, "[setter could not be represented]"),
658
+ );
659
+ }
660
+ }
661
+ if (typeof key === "symbol") {
662
+ const symbolProperty = Object.create(null);
663
+ defineDiagnosticProperty(
664
+ symbolProperty,
665
+ "key",
666
+ diagnosticText(key, "[symbol key could not be represented]"),
667
+ );
668
+ defineDiagnosticProperty(symbolProperty, "descriptor", projected);
669
+ symbolProperties.push(symbolProperty);
670
+ continue;
671
+ }
672
+ defineDiagnosticProperty(
673
+ result,
674
+ key,
675
+ Object.hasOwn(projected, "value") ? projected.value : projected,
676
+ );
677
+ }
678
+
679
+ for (const key of ["name", "message", "stack", "code", "reason", "details", "cause"]) {
680
+ if (Object.hasOwn(result, key)) continue;
681
+ try {
682
+ const field = Reflect.get(value, key);
683
+ if (field !== undefined) {
684
+ defineDiagnosticProperty(
685
+ result,
686
+ key,
687
+ serializedDiagnosticValue(field, seen),
688
+ );
689
+ }
690
+ } catch (error) {
691
+ defineDiagnosticProperty(result, key, serializedDiagnosticValue(error, seen));
692
+ }
693
+ }
694
+
695
+ let metadataKey = "$diagnostic";
696
+ while (Object.hasOwn(result, metadataKey)) metadataKey = `$${metadataKey}`;
697
+ const metadata = Object.create(null);
698
+ const valueType = diagnosticType(value);
699
+ defineDiagnosticProperty(metadata, "type", valueType);
700
+ if (symbolProperties.length > 0) {
701
+ defineDiagnosticProperty(metadata, "symbolProperties", symbolProperties);
702
+ }
703
+ try {
704
+ if (type === "function") {
705
+ defineDiagnosticProperty(
706
+ metadata,
707
+ "source",
708
+ diagnosticText(value, "[function could not be represented]"),
709
+ );
710
+ } else if (valueType === "Map") {
711
+ const entries = [];
712
+ for (const [key, entry] of value) {
713
+ entries.push([
714
+ serializedDiagnosticValue(key, seen),
715
+ serializedDiagnosticValue(entry, seen),
716
+ ]);
717
+ }
718
+ defineDiagnosticProperty(metadata, "entries", entries);
719
+ } else if (valueType === "Set") {
720
+ const entries = [];
721
+ for (const entry of value) entries.push(serializedDiagnosticValue(entry, seen));
722
+ defineDiagnosticProperty(metadata, "values", entries);
723
+ } else if (valueType === "Date") {
724
+ defineDiagnosticProperty(metadata, "value", Date.prototype.getTime.call(value));
725
+ } else if (valueType === "RegExp") {
726
+ defineDiagnosticProperty(metadata, "source", value.source);
727
+ defineDiagnosticProperty(metadata, "flags", value.flags);
728
+ defineDiagnosticProperty(metadata, "lastIndex", value.lastIndex);
729
+ } else if (valueType === "ArrayBuffer" || valueType === "SharedArrayBuffer"
730
+ || valueType === "Blob" || valueType === "File") {
731
+ defineDiagnosticProperty(metadata, "value", value);
732
+ } else {
733
+ let view = false;
734
+ try {
735
+ view = ArrayBuffer.isView(value);
736
+ } catch {}
737
+ if (view) defineDiagnosticProperty(metadata, "value", value);
738
+ }
739
+ } catch (error) {
740
+ defineDiagnosticProperty(
741
+ metadata,
742
+ "inspectionError",
743
+ serializedDiagnosticValue(error, seen),
744
+ );
745
+ }
746
+ defineDiagnosticProperty(result, metadataKey, metadata);
747
+ return result;
535
748
  }
536
749
 
537
750
  function workerErrorReasonAdmission(reason, role, op) {
@@ -549,7 +762,10 @@ export function normalizeSpeechWorkerErrorEnvelope(value, role, op) {
549
762
  try {
550
763
  const keys = Reflect.ownKeys(value);
551
764
  if (keys.some((key) => typeof key !== "string")
552
- || keys.sort().join(",") !== "code,message,protocol,reason") return null;
765
+ || ![
766
+ "code,message,protocol,reason",
767
+ "cause,code,message,protocol,reason",
768
+ ].includes(keys.sort().join(","))) return null;
553
769
  descriptors = Object.getOwnPropertyDescriptors(value);
554
770
  } catch {
555
771
  return null;
@@ -563,13 +779,15 @@ export function normalizeSpeechWorkerErrorEnvelope(value, role, op) {
563
779
  const reason = descriptors.reason.value;
564
780
  if (protocol !== SPEECH_WORKER_ERROR_PROTOCOL) return null;
565
781
  if (!Object.hasOwn(WORKER_ERROR_MESSAGES, code)) return null;
566
- if (message !== WORKER_ERROR_MESSAGES[code]) return null;
782
+ if (typeof message !== "string" || message.length < 1) return null;
567
783
  const admission = workerErrorReasonAdmission(reason, role, op);
568
784
  if (admission?.code !== code) return null;
569
- return Object.freeze({
785
+ if (descriptors.cause && !Object.hasOwn(descriptors.cause, "value")) return null;
786
+ return completeValue({
570
787
  code,
571
788
  message,
572
789
  reason,
790
+ ...(descriptors.cause ? { cause: descriptors.cause.value } : {}),
573
791
  });
574
792
  }
575
793
 
@@ -589,6 +807,22 @@ function requiredText(
589
807
  return value.trim();
590
808
  }
591
809
 
810
+ function requiredContent(
811
+ value,
812
+ label,
813
+ reason,
814
+ ) {
815
+ if (typeof value !== "string" || !value.trim()) {
816
+ throw workerError(
817
+ "ARCANE_AI_INVALID_REQUEST",
818
+ `${label} is required.`,
819
+ undefined,
820
+ reason,
821
+ );
822
+ }
823
+ return value;
824
+ }
825
+
592
826
  function requiredSampleRate(value, label, fallback) {
593
827
  const candidate = value ?? fallback;
594
828
  if (!Number.isSafeInteger(candidate) || candidate < 1) {
@@ -695,36 +929,6 @@ function validateConfiguration(configuration, role) {
695
929
  paths.add(file.path);
696
930
  }
697
931
  const runtimePaths = new Set(configuration.runtime.files.map((file) => file.path));
698
- const security = configuration.security;
699
- const securityChecks = security?.checks;
700
- if (
701
- !security
702
- || typeof security !== "object"
703
- || Array.isArray(security)
704
- || typeof security.secure !== "boolean"
705
- || !securityChecks
706
- || typeof securityChecks !== "object"
707
- || Array.isArray(securityChecks)
708
- || typeof securityChecks.byteLength !== "boolean"
709
- || typeof securityChecks.sha256 !== "boolean"
710
- || typeof configuration.runtime.artifactGraphId !== "string"
711
- || !/^[a-f0-9]{64}$/u.test(configuration.runtime.artifactGraphId)
712
- || (
713
- typeof configuration.runtime.guardCapability !== "string"
714
- || !/^[a-f0-9]{64}$/u.test(configuration.runtime.guardCapability)
715
- || !GRAPH_ADMISSIONS.has(configuration.runtime.artifactGraphAdmission)
716
- || !configuration.runtime.edges
717
- || typeof configuration.runtime.edges !== "object"
718
- || !Array.isArray(configuration.runtime.transforms)
719
- )
720
- ) {
721
- throw workerError(
722
- "ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID",
723
- "Artifact graph security, identity, admission, edges, and transforms are required.",
724
- undefined,
725
- "artifact-graph-worker-configuration-incomplete",
726
- );
727
- }
728
932
  const wasm = configuration.runtime.onnxWasm;
729
933
  if (
730
934
  !wasm
@@ -732,17 +936,17 @@ function validateConfiguration(configuration, role) {
732
936
  || !runtimePaths.has(wasm.mjsPath)
733
937
  || !runtimePaths.has(wasm.wasmPath)
734
938
  ) {
735
- throw workerError(
736
- "ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID",
737
- "The authenticated ONNX Runtime Web MJS/WASM pair is incomplete or uses the wrong namespace.",
939
+ throw workerError(
940
+ "ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID",
941
+ "The ONNX Runtime Web MJS/WASM pair is incomplete or uses the wrong namespace.",
738
942
  undefined,
739
943
  "artifact-graph-onnx-wasm-configuration-mismatch",
740
944
  );
741
945
  }
742
946
  if (role === "tts" && wasm.numThreads !== undefined) {
743
- throw workerError(
744
- "ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID",
745
- "Kokoro does not expose a verified numThreads configuration field.",
947
+ throw workerError(
948
+ "ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID",
949
+ "Kokoro does not expose a numThreads configuration field.",
746
950
  undefined,
747
951
  "kokoro-env-num-threads-field-not-exposed",
748
952
  );
@@ -773,17 +977,6 @@ function validateConfiguration(configuration, role) {
773
977
  );
774
978
  }
775
979
  }
776
- if (
777
- configuration.runtime.negativeRuntimeRequestUrls !== undefined
778
- && !Array.isArray(configuration.runtime.negativeRuntimeRequestUrls)
779
- ) {
780
- throw workerError(
781
- "ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID",
782
- "Artifact graph negative runtime request routes must be an array.",
783
- undefined,
784
- "artifact-graph-negative-request-routes-not-array",
785
- );
786
- }
787
980
  }
788
981
  return configuration;
789
982
  }
@@ -804,6 +997,9 @@ function absoluteRequestUrl(value, scope) {
804
997
  }
805
998
  }
806
999
 
1000
+ // Dormant hardening retained for future review only. The closed route reader,
1001
+ // cache admission, and legacy fetch isolation below are not used by ordinary
1002
+ // execution and must not be enabled without explicit user review.
807
1003
  function createArtifactRoutes(scope, configuration) {
808
1004
  const positive = new Map();
809
1005
  const negative = new Set();
@@ -843,7 +1039,7 @@ function createArtifactRoutes(scope, configuration) {
843
1039
  }
844
1040
  negative.add(absolute);
845
1041
  }
846
- return Object.freeze({ files, positive, negative });
1042
+ return completeValue({ files, positive, negative });
847
1043
  }
848
1044
 
849
1045
  function requestMethod(input, init, scope) {
@@ -961,16 +1157,16 @@ function createRouteReader(scope, configuration, originalFetch) {
961
1157
  function resolve(input) {
962
1158
  const absolute = absoluteRequestUrl(input, scope);
963
1159
  const file = routes.positive.get(absolute);
964
- if (file) return Object.freeze({ kind: "file", absolute, file });
1160
+ if (file) return completeValue({ kind: "file", absolute, file });
965
1161
  if (routes.negative.has(absolute)) {
966
- return Object.freeze({ kind: "negative", absolute, file: null });
1162
+ return completeValue({ kind: "negative", absolute, file: null });
967
1163
  }
968
1164
  return null;
969
1165
  }
970
1166
 
971
1167
  function cacheForPaths(targetPaths) {
972
1168
  const admittedPaths = new Set(targetPaths);
973
- return Object.freeze({
1169
+ return completeValue({
974
1170
  async match(input) {
975
1171
  const resolution = resolve(input);
976
1172
  if (
@@ -1015,13 +1211,13 @@ function createRouteReader(scope, configuration, originalFetch) {
1015
1211
  return false;
1016
1212
  },
1017
1213
  async keys() {
1018
- return Object.freeze([]);
1214
+ return completeValue([]);
1019
1215
  },
1020
1216
  });
1021
1217
  }
1022
1218
 
1023
1219
  const cache = cacheForPaths(routes.files.map((file) => file.path));
1024
- return Object.freeze({ cache, cacheForPaths, resolve, responseFor, routes });
1220
+ return completeValue({ cache, cacheForPaths, resolve, responseFor, routes });
1025
1221
  }
1026
1222
 
1027
1223
  function installLegacyAuthorizedFetch(scope, configuration) {
@@ -1061,11 +1257,11 @@ function installLegacyAuthorizedFetch(scope, configuration) {
1061
1257
  authorized,
1062
1258
  "speech-worker-fetch-isolation-unavailable",
1063
1259
  );
1064
- return Object.freeze({ cache: null, cleanup: restore });
1260
+ return completeValue({ cache: null, cleanup: restore });
1065
1261
  }
1066
1262
 
1067
1263
  function installDeniedCacheIsolation(scope) {
1068
- const denied = Object.freeze({
1264
+ const denied = completeValue({
1069
1265
  async open() {
1070
1266
  throw workerError(
1071
1267
  "ARCANE_AI_UNDECLARED_ARTIFACT",
@@ -1086,7 +1282,7 @@ function installDeniedCacheIsolation(scope) {
1086
1282
  return false;
1087
1283
  },
1088
1284
  async keys() {
1089
- return Object.freeze([]);
1285
+ return completeValue([]);
1090
1286
  },
1091
1287
  async delete() {
1092
1288
  return false;
@@ -1234,7 +1430,7 @@ function typedArrayIntrinsics(scope) {
1234
1430
  "artifact-graph-typed-array-validation-unavailable",
1235
1431
  );
1236
1432
  }
1237
- return Object.freeze({
1433
+ return completeValue({
1238
1434
  constructors,
1239
1435
  dataViewPrototype: DataViewConstructor?.prototype ?? null,
1240
1436
  getPrototypeOf: Object.getPrototypeOf,
@@ -1304,6 +1500,9 @@ function nestedWorkerFailureEvent(scope, error) {
1304
1500
  return event;
1305
1501
  }
1306
1502
 
1503
+ // Dormant hardening retained for future review only. Ordinary speech execution
1504
+ // never installs this guard, its declared-edge admission, or its isolation
1505
+ // controls. Do not enable it for secure mode without explicit user review.
1307
1506
  function createArtifactGraphGuard(scope, configuration, role, reader, originalWorker) {
1308
1507
  const files = runtimeFileMap(configuration);
1309
1508
  const edges = configuration.runtime.edges;
@@ -1366,7 +1565,7 @@ function createArtifactGraphGuard(scope, configuration, role, reader, originalWo
1366
1565
  return true;
1367
1566
  }
1368
1567
 
1369
- const guard = Object.freeze({
1568
+ const guard = completeValue({
1370
1569
  protocol: "arcane-ai-browser-speech-artifact-graph-runtime/1",
1371
1570
 
1372
1571
  async dynamicImport(capability, modulePath, occurrence, specifier) {
@@ -1487,7 +1686,7 @@ function createArtifactGraphGuard(scope, configuration, role, reader, originalWo
1487
1686
  event.stopImmediatePropagation?.();
1488
1687
  const admitted = normalizeSpeechWorkerErrorEnvelope(event.data.error, role, "load");
1489
1688
  const failure = admitted
1490
- ? workerError(admitted.code, admitted.message, undefined, admitted.reason)
1689
+ ? workerError(admitted.code, admitted.message, admitted.cause, admitted.reason)
1491
1690
  : workerError(
1492
1691
  "ARCANE_AI_WORKER_MESSAGE_ERROR",
1493
1692
  "The authenticated artifact module Worker error envelope was rejected.",
@@ -1555,7 +1754,7 @@ function createArtifactGraphGuard(scope, configuration, role, reader, originalWo
1555
1754
  },
1556
1755
  });
1557
1756
 
1558
- return Object.freeze({
1757
+ return completeValue({
1559
1758
  guard,
1560
1759
  transformersCache: (() => {
1561
1760
  const edgesForTransformers = [...cacheOpens.values()].filter((edge) =>
@@ -1650,7 +1849,6 @@ function installStringTimerIsolation(scope, name) {
1650
1849
  function installArtifactGraphEnvironment(scope, configuration, role) {
1651
1850
  const originalFetch = scope.fetch?.bind(scope);
1652
1851
  const originalWorker = scope.Worker;
1653
- const strictSecurity = configuration.security?.secure === true;
1654
1852
  if (typeof originalFetch !== "function") {
1655
1853
  throw workerError(
1656
1854
  "ARCANE_AI_PROVIDER_UNAVAILABLE",
@@ -1677,120 +1875,18 @@ function installArtifactGraphEnvironment(scope, configuration, role) {
1677
1875
  );
1678
1876
  const restores = [];
1679
1877
  try {
1680
- if (strictSecurity) {
1681
- restores.push(installDynamicCodeConstructorIsolation());
1682
- restores.push(installStringTimerIsolation(scope, "setInterval"));
1683
- restores.push(installStringTimerIsolation(scope, "setTimeout"));
1684
- if ("indexedDB" in scope) {
1685
- restores.push(installScopeValue(
1686
- scope,
1687
- "indexedDB",
1688
- undefined,
1689
- "artifact-graph-indexeddb-isolation-unavailable",
1690
- ));
1691
- }
1692
- if (scope.navigator && "storage" in scope.navigator) {
1693
- restores.push(installObjectValue(
1694
- scope.navigator,
1695
- "storage",
1696
- undefined,
1697
- "WorkerNavigator.storage",
1698
- "artifact-graph-opfs-isolation-unavailable",
1699
- ));
1700
- }
1701
- }
1702
1878
  restores.push(installScopeValue(
1703
1879
  scope,
1704
1880
  GRAPH_GUARD_NAME,
1705
1881
  graphGuard.guard,
1706
1882
  "artifact-graph-guard-global-definition-rejected",
1707
1883
  ));
1708
- if (strictSecurity) {
1709
- restores.push(installScopeValue(
1710
- scope,
1711
- "fetch",
1712
- async function rejectUntransformedArtifactGraphFetch() {
1713
- throw workerError(
1714
- "ARCANE_AI_ARTIFACT_GRAPH_FETCH_EDGE_UNDECLARED",
1715
- "Artifact graph fetch must use its declared transformed edge.",
1716
- undefined,
1717
- "artifact-graph-fetch-guard-bypassed",
1718
- );
1719
- },
1720
- "artifact-graph-fetch-isolation-unavailable",
1721
- ));
1722
- const cacheStorage = Object.freeze({
1723
- async open() {
1724
- throw workerError(
1725
- "ARCANE_AI_ARTIFACT_GRAPH_CACHE_EDGE_UNDECLARED",
1726
- "Artifact graph CacheStorage.open must use its declared transformed edge.",
1727
- undefined,
1728
- "artifact-graph-cache-open-guard-bypassed",
1729
- );
1730
- },
1731
- async match() {
1732
- throw workerError(
1733
- "ARCANE_AI_ARTIFACT_GRAPH_CACHE_EDGE_UNDECLARED",
1734
- "Artifact graph CacheStorage.match requires a declared cache-open edge.",
1735
- undefined,
1736
- "artifact-graph-cache-match-guard-bypassed",
1737
- );
1738
- },
1739
- async has() {
1740
- return true;
1741
- },
1742
- async keys() {
1743
- return Object.freeze([]);
1744
- },
1745
- async delete() {
1746
- return false;
1747
- },
1748
- });
1749
- restores.push(installScopeValue(
1750
- scope,
1751
- "caches",
1752
- cacheStorage,
1753
- "artifact-graph-cache-isolation-unavailable",
1754
- ));
1755
-
1756
- const deniedCapabilities = [
1757
- "BroadcastChannel",
1758
- "EventSource",
1759
- "Function",
1760
- "RTCPeerConnection",
1761
- "ShadowRealm",
1762
- "SharedWorker",
1763
- "WebSocket",
1764
- "WebSocketStream",
1765
- "WebTransport",
1766
- "Worker",
1767
- "XMLHttpRequest",
1768
- "eval",
1769
- "importScripts",
1770
- ];
1771
- for (const name of deniedCapabilities) {
1772
- if (!(name in scope)) continue;
1773
- restores.push(installScopeValue(
1774
- scope,
1775
- name,
1776
- function rejectUndeclaredArtifactGraphCapability() {
1777
- throw workerError(
1778
- "ARCANE_AI_ARTIFACT_GRAPH_ISOLATION_UNAVAILABLE",
1779
- `The authenticated artifact graph denied raw ${name} access.`,
1780
- undefined,
1781
- `artifact-graph-${name.toLowerCase()}-capability-undeclared`,
1782
- );
1783
- },
1784
- `artifact-graph-${name.toLowerCase()}-isolation-unavailable`,
1785
- ));
1786
- }
1787
- }
1788
1884
  } catch (error) {
1789
1885
  restoreScopeValues(restores);
1790
1886
  graphGuard.cleanup();
1791
1887
  throw error;
1792
1888
  }
1793
- return Object.freeze({
1889
+ return completeValue({
1794
1890
  cache: graphGuard.transformersCache,
1795
1891
  cleanup() {
1796
1892
  graphGuard.cleanup();
@@ -1799,6 +1895,300 @@ function installArtifactGraphEnvironment(scope, configuration, role) {
1799
1895
  });
1800
1896
  }
1801
1897
 
1898
+ function ordinaryRequestUrl(value, scope, base = scope.location?.href) {
1899
+ const input = typeof value === "string" || value instanceof URL
1900
+ ? String(value)
1901
+ : value?.url;
1902
+ if (typeof input !== "string" || input.length < 1) return null;
1903
+ try {
1904
+ return new URL(input, base).href;
1905
+ } catch {
1906
+ return null;
1907
+ }
1908
+ }
1909
+
1910
+ function isBareModuleSpecifier(value) {
1911
+ return typeof value === "string"
1912
+ && !value.startsWith("./")
1913
+ && !value.startsWith("../")
1914
+ && !value.startsWith("/")
1915
+ && !/^[A-Za-z][A-Za-z\d+.-]*:/u.test(value);
1916
+ }
1917
+
1918
+ function createOrdinaryRoutes(scope, configuration) {
1919
+ const files = [
1920
+ ...configuration.runtime.files,
1921
+ ...configuration.model.files,
1922
+ ];
1923
+ const filesByPath = new Map(files.map((file) => [file.path, file]));
1924
+ const routes = new Map();
1925
+ const ambiguous = new Set();
1926
+
1927
+ function add(route, file) {
1928
+ const absolute = ordinaryRequestUrl(route, scope);
1929
+ if (!absolute || ambiguous.has(absolute)) return;
1930
+ const existing = routes.get(absolute);
1931
+ if (existing && existing.path !== file.path) {
1932
+ routes.delete(absolute);
1933
+ ambiguous.add(absolute);
1934
+ return;
1935
+ }
1936
+ routes.set(absolute, file);
1937
+ }
1938
+
1939
+ for (const file of files) {
1940
+ add(file.sourceUrl, file);
1941
+ add(file.moduleUrl, file);
1942
+ for (const route of file.runtimeRequestUrls ?? []) add(route, file);
1943
+ }
1944
+ return completeValue({ files, filesByPath, routes });
1945
+ }
1946
+
1947
+ function createOrdinaryRouteReader(
1948
+ scope,
1949
+ configuration,
1950
+ originalFetch,
1951
+ originalCaches,
1952
+ ) {
1953
+ const routeTable = createOrdinaryRoutes(scope, configuration);
1954
+ const nativeCaches = new Map();
1955
+ const RequestConstructor = scope.Request ?? globalThis.Request;
1956
+
1957
+ function sourceBase(modulePath) {
1958
+ return routeTable.filesByPath.get(modulePath)?.sourceUrl ?? scope.location?.href;
1959
+ }
1960
+
1961
+ function nativeInput(input, modulePath) {
1962
+ if (typeof input !== "string" && !(input instanceof URL)) return input;
1963
+ return ordinaryRequestUrl(input, scope, sourceBase(modulePath)) ?? input;
1964
+ }
1965
+
1966
+ function resolve(input, modulePath) {
1967
+ const absolute = ordinaryRequestUrl(input, scope, sourceBase(modulePath));
1968
+ const file = absolute ? routeTable.routes.get(absolute) : null;
1969
+ return file ? completeValue({ absolute, file }) : null;
1970
+ }
1971
+
1972
+ function responseFor(resolution, input, init) {
1973
+ const mappedInput = typeof RequestConstructor === "function"
1974
+ && input instanceof RequestConstructor
1975
+ ? new RequestConstructor(resolution.file.moduleUrl, input)
1976
+ : resolution.file.moduleUrl;
1977
+ return originalFetch(mappedInput, init);
1978
+ }
1979
+
1980
+ async function nativeCache(name) {
1981
+ if (!originalCaches || typeof originalCaches.open !== "function") return null;
1982
+ if (!nativeCaches.has(name)) {
1983
+ nativeCaches.set(name, Promise.resolve(originalCaches.open.call(originalCaches, name)));
1984
+ }
1985
+ return nativeCaches.get(name);
1986
+ }
1987
+
1988
+ function cacheForName(name, modulePath) {
1989
+ return completeValue({
1990
+ async match(input, options) {
1991
+ const resolution = resolve(input, modulePath);
1992
+ if (resolution) return responseFor(resolution, input);
1993
+ const cache = await nativeCache(name);
1994
+ return cache?.match(nativeInput(input, modulePath), options);
1995
+ },
1996
+ async put(input, response) {
1997
+ const cache = await nativeCache(name);
1998
+ if (!cache) throw new TypeError("Browser CacheStorage is unavailable.");
1999
+ return cache.put(nativeInput(input, modulePath), response);
2000
+ },
2001
+ async add(input) {
2002
+ const cache = await nativeCache(name);
2003
+ if (!cache) throw new TypeError("Browser CacheStorage is unavailable.");
2004
+ return cache.add(nativeInput(input, modulePath));
2005
+ },
2006
+ async addAll(inputs) {
2007
+ const cache = await nativeCache(name);
2008
+ if (!cache) throw new TypeError("Browser CacheStorage is unavailable.");
2009
+ return cache.addAll(Array.from(inputs, (input) => nativeInput(input, modulePath)));
2010
+ },
2011
+ async delete(input, options) {
2012
+ const cache = await nativeCache(name);
2013
+ return cache ? cache.delete(nativeInput(input, modulePath), options) : false;
2014
+ },
2015
+ async keys(input, options) {
2016
+ const cache = await nativeCache(name);
2017
+ if (!cache) return [];
2018
+ return input === undefined
2019
+ ? cache.keys()
2020
+ : cache.keys(nativeInput(input, modulePath), options);
2021
+ },
2022
+ });
2023
+ }
2024
+
2025
+ return completeValue({ cacheForName, nativeInput, resolve, responseFor });
2026
+ }
2027
+
2028
+ function createOrdinaryArtifactModuleRouter(
2029
+ scope,
2030
+ configuration,
2031
+ role,
2032
+ reader,
2033
+ originalFetch,
2034
+ originalWorker,
2035
+ ) {
2036
+ const nestedWorkers = new Set();
2037
+ const router = completeValue({
2038
+ async dynamicImport(modulePath, specifier) {
2039
+ const resolution = isBareModuleSpecifier(specifier)
2040
+ ? null
2041
+ : reader.resolve(specifier, modulePath);
2042
+ const target = resolution?.file.moduleUrl
2043
+ ?? (isBareModuleSpecifier(specifier)
2044
+ ? specifier
2045
+ : reader.nativeInput(specifier, modulePath));
2046
+ return import(target);
2047
+ },
2048
+
2049
+ fetch(modulePath, input, init) {
2050
+ const resolution = reader.resolve(input, modulePath);
2051
+ return resolution
2052
+ ? reader.responseFor(resolution, input, init)
2053
+ : originalFetch(reader.nativeInput(input, modulePath), init);
2054
+ },
2055
+
2056
+ openCache(modulePath, name) {
2057
+ return Promise.resolve(reader.cacheForName(name, modulePath));
2058
+ },
2059
+
2060
+ createWorker(modulePath, specifier, options = {}) {
2061
+ if (typeof originalWorker !== "function") {
2062
+ throw workerError(
2063
+ "ARCANE_AI_PROVIDER_UNAVAILABLE",
2064
+ "Nested browser Workers are unavailable.",
2065
+ undefined,
2066
+ "speech-module-worker-constructor-unavailable",
2067
+ );
2068
+ }
2069
+ const resolution = reader.resolve(specifier, modulePath);
2070
+ if (!resolution) {
2071
+ return new originalWorker(reader.nativeInput(specifier, modulePath), options);
2072
+ }
2073
+ const workerOptions = options && typeof options === "object"
2074
+ ? { ...options, type: "module" }
2075
+ : { type: "module" };
2076
+ const worker = new originalWorker(nestedWorkerUrl(role), workerOptions);
2077
+ nestedWorkers.add(worker);
2078
+ const onBootstrapMessage = (event) => {
2079
+ if (event.data?.protocol !== NESTED_WORKER_PROTOCOL
2080
+ || event.data?.event !== "artifact-module-worker-bootstrap-rejected") return;
2081
+ event.stopImmediatePropagation?.();
2082
+ const admitted = normalizeSpeechWorkerErrorEnvelope(event.data.error, role, "load");
2083
+ const failure = admitted
2084
+ ? workerError(admitted.code, admitted.message, admitted.cause, admitted.reason)
2085
+ : workerError(
2086
+ "ARCANE_AI_WORKER_MESSAGE_ERROR",
2087
+ "The artifact module Worker error envelope was rejected.",
2088
+ undefined,
2089
+ "speech-module-worker-error-envelope-rejected",
2090
+ );
2091
+ worker.dispatchEvent?.(nestedWorkerFailureEvent(scope, failure));
2092
+ };
2093
+ worker.addEventListener?.("message", onBootstrapMessage);
2094
+ try {
2095
+ worker.postMessage({
2096
+ protocol: NESTED_WORKER_PROTOCOL,
2097
+ op: "initialize-artifact-module-worker",
2098
+ role,
2099
+ targetPath: resolution.file.path,
2100
+ configuration,
2101
+ });
2102
+ } catch (error) {
2103
+ nestedWorkers.delete(worker);
2104
+ worker.terminate();
2105
+ throw workerError(
2106
+ "ARCANE_AI_WORKER_MESSAGE_ERROR",
2107
+ "The artifact module Worker initialization message was rejected.",
2108
+ error,
2109
+ "speech-module-worker-initialization-message-rejected",
2110
+ );
2111
+ }
2112
+ return worker;
2113
+ },
2114
+ });
2115
+ return completeValue({
2116
+ router,
2117
+ transformersCache: reader.cacheForName("transformers-cache", null),
2118
+ cleanup() {
2119
+ for (const worker of nestedWorkers) {
2120
+ try {
2121
+ worker.terminate();
2122
+ } catch {
2123
+ // The owning speech Worker is already being torn down.
2124
+ }
2125
+ }
2126
+ nestedWorkers.clear();
2127
+ },
2128
+ });
2129
+ }
2130
+
2131
+ function installOrdinaryArtifactModuleRouter(scope, configuration, role) {
2132
+ const originalFetch = scope.fetch?.bind(scope);
2133
+ const originalWorker = scope.Worker;
2134
+ const originalCaches = scope.caches;
2135
+ if (typeof originalFetch !== "function") {
2136
+ throw workerError(
2137
+ "ARCANE_AI_PROVIDER_UNAVAILABLE",
2138
+ "Browser fetch is unavailable in the speech Worker.",
2139
+ undefined,
2140
+ "speech-worker-fetch-unavailable",
2141
+ );
2142
+ }
2143
+ const reader = createOrdinaryRouteReader(
2144
+ scope,
2145
+ configuration,
2146
+ originalFetch,
2147
+ originalCaches,
2148
+ );
2149
+ const moduleRouter = createOrdinaryArtifactModuleRouter(
2150
+ scope,
2151
+ configuration,
2152
+ role,
2153
+ reader,
2154
+ originalFetch,
2155
+ originalWorker,
2156
+ );
2157
+ const hadOwn = Object.prototype.hasOwnProperty.call(scope, MODULE_ROUTER_NAME);
2158
+ const previous = scope[MODULE_ROUTER_NAME];
2159
+ try {
2160
+ scope[MODULE_ROUTER_NAME] = moduleRouter.router;
2161
+ if (scope[MODULE_ROUTER_NAME] !== moduleRouter.router) {
2162
+ Object.defineProperty(scope, MODULE_ROUTER_NAME, {
2163
+ configurable: true,
2164
+ enumerable: true,
2165
+ writable: true,
2166
+ value: moduleRouter.router,
2167
+ });
2168
+ }
2169
+ } catch (error) {
2170
+ moduleRouter.cleanup();
2171
+ throw workerError(
2172
+ "ARCANE_AI_PROVIDER_UNAVAILABLE",
2173
+ "The speech Worker cannot install the artifact module router.",
2174
+ error,
2175
+ "speech-module-router-unavailable",
2176
+ );
2177
+ }
2178
+ return completeValue({
2179
+ cache: moduleRouter.transformersCache,
2180
+ cleanup() {
2181
+ moduleRouter.cleanup();
2182
+ try {
2183
+ if (hadOwn) scope[MODULE_ROUTER_NAME] = previous;
2184
+ else delete scope[MODULE_ROUTER_NAME];
2185
+ } catch {
2186
+ // Worker teardown releases the remaining module router reference.
2187
+ }
2188
+ },
2189
+ });
2190
+ }
2191
+
1802
2192
  function assignSetting(object, name, value, cleanup, {
1803
2193
  allowCreate = false,
1804
2194
  assignmentRejectedReason,
@@ -1856,14 +2246,6 @@ function assignSetting(object, name, value, cleanup, {
1856
2246
 
1857
2247
  function configuredWasmPaths(configuration) {
1858
2248
  if (configuration.runtime.wasmPaths !== undefined) {
1859
- if (configuration.security?.secure === true) {
1860
- throw workerError(
1861
- "ARCANE_AI_INVALID_REQUEST",
1862
- "Secure browser speech cannot use remote wasmPaths.",
1863
- undefined,
1864
- "speech-worker-secure-remote-wasm-paths-rejected",
1865
- );
1866
- }
1867
2249
  return configuration.runtime.wasmPaths;
1868
2250
  }
1869
2251
  const byPath = new Map(configuration.runtime.files.map((file) => [file.path, file]));
@@ -1884,12 +2266,11 @@ function configuredWasmPaths(configuration) {
1884
2266
  "artifact-graph-onnx-wasm-pair-not-materialized",
1885
2267
  );
1886
2268
  }
1887
- return Object.freeze({ mjs: mjs.moduleUrl, wasm: wasm.moduleUrl });
2269
+ return completeValue({ mjs: mjs.moduleUrl, wasm: wasm.moduleUrl });
1888
2270
  }
1889
2271
 
1890
2272
  function configureRuntimeNamespace(namespace, configuration, role, cache) {
1891
2273
  const cleanup = [];
1892
- const strictSecurity = configuration.security?.secure === true;
1893
2274
  const restoreSettings = () => {
1894
2275
  for (const restore of cleanup.splice(0).reverse()) {
1895
2276
  try {
@@ -1949,24 +2330,6 @@ function configureRuntimeNamespace(namespace, configuration, role, cache) {
1949
2330
  assignmentRejectedReason: "transformers-env-allow-remote-models-assignment-rejected",
1950
2331
  unavailableReason: "transformers-env-allow-remote-models-unavailable",
1951
2332
  });
1952
- if (strictSecurity) {
1953
- assignSetting(env, "useBrowserCache", false, cleanup, {
1954
- assignmentRejectedReason: "transformers-env-browser-cache-assignment-rejected",
1955
- unavailableReason: "transformers-env-browser-cache-unavailable",
1956
- });
1957
- assignSetting(env, "useFSCache", false, cleanup, {
1958
- assignmentRejectedReason: "transformers-env-fs-cache-assignment-rejected",
1959
- unavailableReason: "transformers-env-fs-cache-unavailable",
1960
- });
1961
- assignSetting(env, "useCustomCache", cache !== null, cleanup, {
1962
- assignmentRejectedReason: "transformers-env-custom-cache-toggle-assignment-rejected",
1963
- unavailableReason: "transformers-env-custom-cache-toggle-unavailable",
1964
- });
1965
- assignSetting(env, "customCache", cache, cleanup, {
1966
- assignmentRejectedReason: "transformers-env-custom-cache-assignment-rejected",
1967
- unavailableReason: "transformers-env-custom-cache-unavailable",
1968
- });
1969
- }
1970
2333
  if (paths) {
1971
2334
  assignSetting(
1972
2335
  wasm,
@@ -2000,39 +2363,6 @@ function configureRuntimeNamespace(namespace, configuration, role, cache) {
2000
2363
  return restoreSettings;
2001
2364
  }
2002
2365
 
2003
- function workerProgress(send, role, requestId, phase, completed = 0, total = null, unit = "items") {
2004
- send({
2005
- protocol: SPEECH_WORKER_PROTOCOL,
2006
- event: "progress",
2007
- requestId,
2008
- progress: Object.freeze({
2009
- phase,
2010
- completed,
2011
- total,
2012
- unit,
2013
- heartbeat: true,
2014
- }),
2015
- }, []);
2016
- }
2017
-
2018
- function upstreamProgress(send, role, requestId) {
2019
- return function reportSpeechModelProgress(update = {}) {
2020
- const completed = Number.isFinite(update.loaded)
2021
- ? update.loaded
2022
- : Number.isFinite(update.progress) ? update.progress : 0;
2023
- const total = Number.isFinite(update.total) ? update.total : null;
2024
- workerProgress(
2025
- send,
2026
- role,
2027
- requestId,
2028
- `${role}-model-load-progress`,
2029
- completed,
2030
- total,
2031
- Number.isFinite(update.loaded) ? "bytes" : "items",
2032
- );
2033
- };
2034
- }
2035
-
2036
2366
  async function disposeEngine(engine) {
2037
2367
  if (!engine) return;
2038
2368
  if (typeof engine.dispose === "function") {
@@ -2077,12 +2407,12 @@ async function createWhisperEngine(namespace, configuration, signal, report) {
2077
2407
  }
2078
2408
  throw error;
2079
2409
  }
2080
- return Object.freeze({
2410
+ return completeValue({
2081
2411
  async transcribe(input, { signal: requestSignal } = {}) {
2082
2412
  throwIfAborted(requestSignal, "stt-transcription-cancelled");
2083
2413
  const output = await transcriber(input.audio, { signal: requestSignal });
2084
2414
  throwIfAborted(requestSignal, "stt-transcription-cancelled");
2085
- return Object.freeze({ text: String(output?.text ?? "").trim() });
2415
+ return completeValue({ text: String(output?.text ?? "") });
2086
2416
  },
2087
2417
  dispose: () => disposeEngine(transcriber),
2088
2418
  });
@@ -2117,7 +2447,7 @@ async function createKokoroEngine(namespace, configuration, signal, report) {
2117
2447
  }
2118
2448
  throw error;
2119
2449
  }
2120
- return Object.freeze({
2450
+ return completeValue({
2121
2451
  async synthesize(input, { signal: requestSignal } = {}) {
2122
2452
  throwIfAborted(requestSignal, "tts-synthesis-cancelled");
2123
2453
  const output = await synthesizer.generate(input.text, {
@@ -2129,7 +2459,7 @@ async function createKokoroEngine(namespace, configuration, signal, report) {
2129
2459
  const audio = output?.audio instanceof Float32Array
2130
2460
  ? output.audio
2131
2461
  : new Float32Array(output?.audio ?? []);
2132
- return Object.freeze({
2462
+ return completeValue({
2133
2463
  audio,
2134
2464
  sampleRate: output?.sampling_rate,
2135
2465
  voice: input.voice,
@@ -2167,9 +2497,9 @@ function validateInput(role, payload, configuration) {
2167
2497
  "stt-transcription-sample-rate-mismatch",
2168
2498
  );
2169
2499
  }
2170
- return Object.freeze({ audio: payload.audio, sampleRate: inputSampleRate });
2500
+ return completeValue({ audio: payload.audio, sampleRate: inputSampleRate });
2171
2501
  }
2172
- const text = requiredText(payload?.text, "Kokoro text", "tts-synthesis-text-empty");
2502
+ const text = requiredContent(payload?.text, "Kokoro text", "tts-synthesis-text-empty");
2173
2503
  const voice = requiredText(
2174
2504
  payload?.voice ?? configuration.model.defaultVoice,
2175
2505
  "Kokoro voice",
@@ -2185,15 +2515,15 @@ function validateInput(role, payload, configuration) {
2185
2515
  );
2186
2516
  }
2187
2517
  const speed = payload?.speed ?? 1;
2188
- if (!Number.isFinite(speed) || speed <= 0 || speed > 4) {
2518
+ if (!Number.isFinite(speed) || speed <= 0) {
2189
2519
  throw workerError(
2190
2520
  "ARCANE_AI_INVALID_REQUEST",
2191
- "Kokoro speed must be greater than 0 and at most 4.",
2521
+ "Kokoro speed must be greater than 0.",
2192
2522
  undefined,
2193
- "tts-synthesis-speed-out-of-range",
2523
+ "tts-synthesis-speed-not-positive",
2194
2524
  );
2195
2525
  }
2196
- return Object.freeze({ text, voice, speed });
2526
+ return completeValue({ text, voice, speed });
2197
2527
  }
2198
2528
 
2199
2529
  function validateResult(role, result, configuration) {
@@ -2206,7 +2536,7 @@ function validateResult(role, result, configuration) {
2206
2536
  "stt-transcription-result-text-not-string",
2207
2537
  );
2208
2538
  }
2209
- return Object.freeze({ text: result.text.trim() });
2539
+ return completeValue({ text: result.text });
2210
2540
  }
2211
2541
  const outputSampleRate = requiredSampleRate(
2212
2542
  configuration.model.outputSampleRate,
@@ -2239,7 +2569,7 @@ function validateResult(role, result, configuration) {
2239
2569
  );
2240
2570
  }
2241
2571
  }
2242
- return Object.freeze({
2572
+ return completeValue({
2243
2573
  audio: result.audio,
2244
2574
  sampleRate: outputSampleRate,
2245
2575
  voice: result.voice,
@@ -2264,16 +2594,7 @@ export function createSpeechWorkerRuntime({ role, scope = globalThis, send } = {
2264
2594
 
2265
2595
  function status() {
2266
2596
  const state = disposed ? "disposed" : engine ? "ready" : "unloaded";
2267
- const security = configuration?.security
2268
- ? Object.freeze({
2269
- secure: configuration.security.secure === true,
2270
- checks: Object.freeze({
2271
- byteLength: configuration.security.checks?.byteLength === true,
2272
- sha256: configuration.security.checks?.sha256 === true,
2273
- }),
2274
- })
2275
- : null;
2276
- return Object.freeze({
2597
+ return completeValue({
2277
2598
  state,
2278
2599
  lifecycleStatus: `${role}-worker-${state}`,
2279
2600
  lifecycleReason,
@@ -2281,9 +2602,6 @@ export function createSpeechWorkerRuntime({ role, scope = globalThis, send } = {
2281
2602
  loaded: engine !== null,
2282
2603
  busy: operations.size > 0,
2283
2604
  activeOperation: operations.values().next().value?.publicOperation ?? null,
2284
- security,
2285
- artifactGraphId: configuration?.runtime?.artifactGraphId ?? null,
2286
- artifactGraphAdmission: configuration?.runtime?.artifactGraphAdmission ?? null,
2287
2605
  });
2288
2606
  }
2289
2607
 
@@ -2304,32 +2622,13 @@ export function createSpeechWorkerRuntime({ role, scope = globalThis, send } = {
2304
2622
  const entry = configuration.runtime.files.find((file) =>
2305
2623
  file.path === configuration.runtime.entry);
2306
2624
  if (graphConfiguration(configuration)) {
2307
- environment = installArtifactGraphEnvironment(scope, configuration, role);
2308
- } else if (configuration.security?.secure === true) {
2309
- const legacyFetch = installLegacyAuthorizedFetch(scope, configuration);
2310
- try {
2311
- const restoreCaches = installDeniedCacheIsolation(scope);
2312
- environment = Object.freeze({
2313
- cache: null,
2314
- cleanup() {
2315
- try {
2316
- restoreCaches();
2317
- } finally {
2318
- legacyFetch.cleanup();
2319
- }
2320
- },
2321
- });
2322
- } catch (error) {
2323
- legacyFetch.cleanup();
2324
- throw error;
2325
- }
2625
+ environment = installOrdinaryArtifactModuleRouter(scope, configuration, role);
2326
2626
  } else {
2327
- environment = Object.freeze({
2627
+ environment = completeValue({
2328
2628
  cache: null,
2329
2629
  cleanup() {},
2330
2630
  });
2331
2631
  }
2332
- workerProgress(send, role, request.id, `${role}-runtime-import-started`);
2333
2632
  loadFailureReason = `${role}-worker-runtime-import-rejected`;
2334
2633
  const namespace = await import(entry.moduleUrl);
2335
2634
  throwIfAborted(signal, `${role}-load-cancelled`);
@@ -2339,14 +2638,12 @@ export function createSpeechWorkerRuntime({ role, scope = globalThis, send } = {
2339
2638
  role,
2340
2639
  environment.cache,
2341
2640
  );
2342
- workerProgress(send, role, request.id, `${role}-model-load-started`);
2343
2641
  loadFailureReason = `${role}-worker-model-load-rejected`;
2344
- const report = upstreamProgress(send, role, request.id);
2642
+ const report = () => undefined;
2345
2643
  engine = role === "stt"
2346
2644
  ? await createWhisperEngine(namespace, configuration, signal, report)
2347
2645
  : await createKokoroEngine(namespace, configuration, signal, report);
2348
2646
  lifecycleReason = `${role}-load-completed`;
2349
- workerProgress(send, role, request.id, `${role}-provider-ready`, 1, 1);
2350
2647
  return status();
2351
2648
  } catch (error) {
2352
2649
  const failure = admitWorkerFailure(
@@ -2486,12 +2783,15 @@ export function createSpeechWorkerRuntime({ role, scope = globalThis, send } = {
2486
2783
  id: request.id,
2487
2784
  ok: true,
2488
2785
  result: result ?? null,
2489
- }, collectSpeechTransferables(result)), (error) => send({
2490
- protocol: SPEECH_WORKER_PROTOCOL,
2491
- id: request.id,
2492
- ok: false,
2493
- error: serializedError(error, role, op),
2494
- }, []));
2786
+ }, collectSpeechTransferables(result)), (error) => {
2787
+ const response = {
2788
+ protocol: SPEECH_WORKER_PROTOCOL,
2789
+ id: request.id,
2790
+ ok: false,
2791
+ error: null,
2792
+ };
2793
+ sendSerializedError(send, response, error, role, op, scope);
2794
+ });
2495
2795
  }
2496
2796
 
2497
2797
  function handleMessage(request) {
@@ -2517,7 +2817,7 @@ export function createSpeechWorkerRuntime({ role, scope = globalThis, send } = {
2517
2817
  if (op === "cancel") {
2518
2818
  const target = operations.get(request.payload?.targetId);
2519
2819
  target?.controller.abort(operationReason(role, target.op, "cancelled"));
2520
- const result = Promise.resolve(Object.freeze({
2820
+ const result = Promise.resolve(completeValue({
2521
2821
  cancelled: Boolean(target),
2522
2822
  reason: target
2523
2823
  ? operationReason(role, target.op, "cancelled")
@@ -2542,24 +2842,14 @@ export function createSpeechWorkerRuntime({ role, scope = globalThis, send } = {
2542
2842
  return operation;
2543
2843
  }
2544
2844
 
2545
- return Object.freeze({ handleMessage, status });
2546
- }
2547
-
2548
- function privatePort(value) {
2549
- return value
2550
- && typeof value.postMessage === "function"
2551
- && typeof value.addEventListener === "function"
2552
- ? value
2553
- : null;
2845
+ return completeValue({ handleMessage, status });
2554
2846
  }
2555
2847
 
2556
2848
  export function installBrowserSpeechWorker(role, scope = globalThis) {
2557
- let transport = scope;
2558
- let transportMode = null;
2559
2849
  const runtime = createSpeechWorkerRuntime({
2560
2850
  role,
2561
2851
  scope,
2562
- send: (message, transfers) => transport.postMessage(message, transfers),
2852
+ send: (message, transfers) => scope.postMessage(message, transfers),
2563
2853
  });
2564
2854
 
2565
2855
  function receive(request) {
@@ -2567,38 +2857,6 @@ export function installBrowserSpeechWorker(role, scope = globalThis) {
2567
2857
  }
2568
2858
 
2569
2859
  scope.addEventListener("message", (event) => {
2570
- if (transportMode === "private-message-port") return;
2571
- const requestedPort = privatePort(event.data?.privatePort);
2572
- const isGraphLoad = event.data?.op === "load"
2573
- && graphConfiguration(event.data?.payload?.configuration);
2574
- const isStrictGraphLoad = isGraphLoad
2575
- && event.data?.payload?.configuration?.security?.secure === true;
2576
- if (requestedPort) {
2577
- if (!isStrictGraphLoad || transportMode !== null) return;
2578
- transportMode = "private-message-port";
2579
- transport = requestedPort;
2580
- requestedPort.addEventListener("message", (portEvent) => receive(portEvent.data));
2581
- requestedPort.start?.();
2582
- const { privatePort: ignored, ...request } = event.data;
2583
- void ignored;
2584
- receive(request);
2585
- return;
2586
- }
2587
- if (isStrictGraphLoad) {
2588
- scope.postMessage({
2589
- protocol: SPEECH_WORKER_PROTOCOL,
2590
- id: event.data.id,
2591
- ok: false,
2592
- error: serializedError(workerError(
2593
- "ARCANE_AI_ARTIFACT_GRAPH_ISOLATION_UNAVAILABLE",
2594
- "Strict artifact graph loading requires a private MessagePort.",
2595
- undefined,
2596
- "artifact-graph-private-message-port-missing",
2597
- ), role, "load"),
2598
- });
2599
- return;
2600
- }
2601
- transportMode ??= "worker-global-message";
2602
2860
  receive(event.data);
2603
2861
  });
2604
2862
  return runtime;
@@ -2625,7 +2883,7 @@ export function installBrowserSpeechArtifactModuleWorker(role, scope = globalThi
2625
2883
  }
2626
2884
  const request = event.data;
2627
2885
  if (request?.protocol !== NESTED_WORKER_PROTOCOL
2628
- || request.op !== "initialize-authenticated-artifact-module-worker"
2886
+ || request.op !== "initialize-artifact-module-worker"
2629
2887
  || request.role !== role) return;
2630
2888
  initializing = true;
2631
2889
  void (async () => {
@@ -2642,7 +2900,7 @@ export function installBrowserSpeechArtifactModuleWorker(role, scope = globalThi
2642
2900
  "artifact-graph-module-worker-target-not-materialized",
2643
2901
  );
2644
2902
  }
2645
- environment = installArtifactGraphEnvironment(scope, configuration, role);
2903
+ environment = installOrdinaryArtifactModuleRouter(scope, configuration, role);
2646
2904
  await import(target.moduleUrl);
2647
2905
  scope.removeEventListener("message", bootstrap);
2648
2906
  await new Promise((resolve) => queueMicrotask(resolve));
@@ -2653,17 +2911,27 @@ export function installBrowserSpeechArtifactModuleWorker(role, scope = globalThi
2653
2911
  } catch {
2654
2912
  // Preserve the exact nested Worker bootstrap failure.
2655
2913
  }
2656
- scope.postMessage({
2657
- protocol: NESTED_WORKER_PROTOCOL,
2658
- event: "artifact-module-worker-bootstrap-rejected",
2659
- error: serializedError(error, role, "load"),
2660
- });
2661
- scope.close?.();
2914
+ try {
2915
+ sendSerializedError(
2916
+ (message, transfers) => scope.postMessage(message, transfers),
2917
+ {
2918
+ protocol: NESTED_WORKER_PROTOCOL,
2919
+ event: "artifact-module-worker-bootstrap-rejected",
2920
+ error: null,
2921
+ },
2922
+ error,
2923
+ role,
2924
+ "load",
2925
+ scope,
2926
+ );
2927
+ } finally {
2928
+ scope.close?.();
2929
+ }
2662
2930
  }
2663
2931
  })();
2664
2932
  };
2665
2933
  scope.addEventListener("message", bootstrap);
2666
- return Object.freeze({
2934
+ return completeValue({
2667
2935
  protocol: NESTED_WORKER_PROTOCOL,
2668
2936
  role,
2669
2937
  lifecycleStatus: `${role}-artifact-module-worker-awaiting-initialization`,