arcane-os 0.5.7 → 0.5.9

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 (46) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +39 -27
  3. package/browser-runtime/ai/browser-speech-artifacts.mjs +23 -1683
  4. package/browser-runtime/ai/browser-speech-providers.mjs +353 -143
  5. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +32 -324
  6. package/browser-runtime/ai/speech-worker-client.mjs +51 -14
  7. package/browser-runtime/ai/speech-worker-runtime.mjs +45 -1072
  8. package/browser-runtime/dependencies/strong-type/package.json +22 -23
  9. package/browser-runtime/event-manager.mjs +27 -41
  10. package/package.json +2 -3
  11. package/runtime/arcane/components/chat.html +1 -1
  12. package/runtime/arcane/components/speech.html +8 -38
  13. package/runtime/arcane/components/voice-transcription.html +1 -1
  14. package/runtime/arcane/css/theme.css +1 -1
  15. package/runtime/arcane/entities/Chat.js +12 -7
  16. package/runtime/arcane/modules/AI.js +569 -402
  17. package/runtime/arcane/modules/AIPreferenceTuple.js +1 -1
  18. package/runtime/arcane/modules/AIProviderRuntime.js +129 -68
  19. package/runtime/arcane/modules/AIRuntimeState.js +2 -18
  20. package/runtime/arcane/modules/BrowserTestSuite.js +2 -5
  21. package/runtime/arcane/modules/CalculatorEngine.js +0 -4
  22. package/runtime/arcane/modules/ChatRecords.js +169 -1
  23. package/runtime/arcane/modules/CommunicationHub.js +0 -19
  24. package/runtime/arcane/modules/ConfiguredAIChatSession.js +28 -25
  25. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +4 -5
  26. package/runtime/arcane/modules/DocumentLexicalSearch.js +1 -1
  27. package/runtime/arcane/modules/Errors.js +6 -19
  28. package/runtime/arcane/modules/Mail.js +1 -2
  29. package/runtime/arcane/modules/MailTransport.mjs +1 -3
  30. package/runtime/arcane/modules/OllamaModelIdentifier.js +1 -1
  31. package/runtime/arcane/modules/PersistentAIChatSession.js +5 -5
  32. package/runtime/arcane/modules/ScreenCapture.js +2 -4
  33. package/runtime/arcane/modules/SpeechPlayback.js +0 -27
  34. package/runtime/arcane/modules/WaitForComponent.js +0 -1
  35. package/src/app-descriptor.mjs +1 -1
  36. package/src/doctor.mjs +1 -3
  37. package/src/event-manager.mjs +27 -41
  38. package/src/import-map.mjs +1 -1
  39. package/src/index.mjs +2 -9
  40. package/src/installed-sdk-runtime.mjs +1 -11
  41. package/src/mail-api.mjs +0 -1
  42. package/src/native-provider-loader.mjs +0 -9
  43. package/src/scaffold.mjs +9 -21
  44. package/src/toolchain.mjs +5 -28
  45. package/src/workspace-runtime.mjs +0 -4
  46. package/src/workspace.mjs +2 -23
@@ -13,11 +13,7 @@ const MODEL_AUTHORITY_PROTOCOL = "arcane-ai-model-authority/1";
13
13
  const ARTIFACT_GRAPH_KIND = "browser-speech-authenticated-artifact-graph";
14
14
  const ARTIFACT_GRAPH_MODULE_KIND =
15
15
  "browser-speech-authenticated-artifact-graph";
16
- const ARTIFACT_GRAPH_GUARDS = "__arcaneBrowserSpeechArtifactGraphGuardsV1";
17
16
  const ARTIFACT_MODULE_ROUTER = "__arcaneBrowserSpeechModuleRouterV1";
18
- const MUTABLE_PATH_PATTERN = /\/(?:resolve\/)?(?:main|master|latest)(?:\/|$)/iu;
19
- const ARTIFACT_GRAPH_MUTABLE_SOURCE_PATTERN =
20
- /\/(?:refs\/heads\/(?:main|master)|resolve\/(?:main|master)|(?:main|master|latest))(?:\/|$)|@(?:latest|next)(?:\/|$)/iu;
21
17
  const AUTHORITIES = new WeakSet();
22
18
  const AUTHORITY_METADATA = new WeakMap();
23
19
  const ARTIFACT_GRAPHS = new WeakSet();
@@ -30,7 +26,7 @@ const PLATFORM_CREATE_OBJECT_URL = typeof globalThis.URL?.createObjectURL === "f
30
26
  const PLATFORM_REVOKE_OBJECT_URL = typeof globalThis.URL?.revokeObjectURL === "function"
31
27
  ? globalThis.URL.revokeObjectURL.bind(globalThis.URL)
32
28
  : null;
33
- const LEGACY_ARTIFACT_ERROR_REASONS = completeValue({
29
+ const ARTIFACT_ERROR_REASONS = completeValue({
34
30
  ARCANE_AI_REQUEST_ABORTED: "browser-speech-artifact-preparation-cancelled",
35
31
  ARCANE_AI_STORAGE_BUSY: "browser-speech-artifact-dbopfs-write-lock-unavailable",
36
32
  ARCANE_AI_STORAGE_UNAVAILABLE: "browser-speech-artifact-dbopfs-table-unavailable",
@@ -67,16 +63,8 @@ const ARTIFACT_GRAPH_ONNX_NAMESPACES = new Set([
67
63
  "kokoro-env-wasm-paths",
68
64
  "transformers-env-backends-onnx-wasm",
69
65
  ]);
70
- const ARTIFACT_GRAPH_EDGE_POLICIES = new Set([
71
- "artifact-targets-admitted",
72
- "inactive-runtime-branch-rejected",
73
- ]);
74
- const ARTIFACT_GRAPH_IMPORT_MATCHES = new Set([
75
- "exact-runtime-specifier",
76
- "materialized-module-url",
77
- ]);
78
66
 
79
- function speechError(code, message, cause, reason = LEGACY_ARTIFACT_ERROR_REASONS[code]) {
67
+ function speechError(code, message, cause, reason = ARTIFACT_ERROR_REASONS[code]) {
80
68
  const error = cause === undefined
81
69
  ? new Error(message)
82
70
  : new Error(message, { cause });
@@ -155,29 +143,6 @@ function ordinarySourceUrl(value, label) {
155
143
  return result.href;
156
144
  }
157
145
 
158
- function immutableUrl(value, label) {
159
- let result;
160
- try {
161
- result = new URL(value, globalThis.location?.href);
162
- } catch {
163
- throw new TypeError(`${label} must be an absolute or same-origin URL.`);
164
- }
165
- const sameOrigin = globalThis.location?.origin
166
- && result.origin === globalThis.location.origin;
167
- if (
168
- (result.protocol !== "https:" && !sameOrigin)
169
- || result.username
170
- || result.password
171
- || result.hash
172
- || MUTABLE_PATH_PATTERN.test(result.pathname)
173
- ) {
174
- throw new TypeError(
175
- `${label} must be immutable HTTPS or a same-origin immutable URL without credentials or fragments.`,
176
- );
177
- }
178
- return result.href;
179
- }
180
-
181
146
  function canonicalArtifactPath(
182
147
  value,
183
148
  label,
@@ -302,137 +267,11 @@ function graphRuntimeRequestUrl(value, label) {
302
267
  return result.href;
303
268
  }
304
269
 
305
- function graphRedirectFinalOrigin(value, label) {
306
- const text = artifactGraphText(
307
- value,
308
- label,
309
- "artifact-graph-source-redirect-final-origin-text-required",
310
- );
311
- if (text !== value) {
312
- throw artifactGraphTypeError(
313
- "artifact-graph-source-redirect-final-origin-whitespace-rejected",
314
- `${label} must not contain surrounding whitespace.`,
315
- );
316
- }
317
- let result;
318
- try {
319
- result = new URL(text);
320
- } catch (error) {
321
- throw artifactGraphTypeError(
322
- "artifact-graph-source-redirect-final-origin-not-absolute",
323
- `${label} must be an absolute origin.`,
324
- error,
325
- );
326
- }
327
- if (result.username || result.password) {
328
- throw artifactGraphTypeError(
329
- "artifact-graph-source-redirect-final-origin-credentials-rejected",
330
- `${label} must not contain credentials.`,
331
- );
332
- }
333
- if (result.pathname !== "/") {
334
- throw artifactGraphTypeError(
335
- "artifact-graph-source-redirect-final-origin-path-rejected",
336
- `${label} must not contain a path.`,
337
- );
338
- }
339
- if (result.search) {
340
- throw artifactGraphTypeError(
341
- "artifact-graph-source-redirect-final-origin-query-rejected",
342
- `${label} must not contain a query.`,
343
- );
344
- }
345
- if (result.hash) {
346
- throw artifactGraphTypeError(
347
- "artifact-graph-source-redirect-final-origin-fragment-rejected",
348
- `${label} must not contain a fragment.`,
349
- );
350
- }
351
- return result.origin;
352
- }
353
-
354
- function normalizeGraphRedirectFinalOrigins(value, path) {
355
- if (value === undefined) return completeValue([]);
356
- if (!Array.isArray(value)) {
357
- throw artifactGraphTypeError(
358
- "artifact-graph-source-redirect-final-origins-not-array",
359
- `Artifact graph file ${path} redirectFinalOrigins must be an array.`,
360
- );
361
- }
362
- if (value.length < 1) {
363
- throw artifactGraphTypeError(
364
- "artifact-graph-source-redirect-final-origin-inventory-empty",
365
- `Artifact graph file ${path} redirectFinalOrigins must contain at least one final origin when supplied.`,
366
- );
367
- }
368
- const origins = value.map((origin, index) => graphRedirectFinalOrigin(
369
- origin,
370
- `Artifact graph file ${path} redirectFinalOrigins[${String(index)}]`,
371
- ));
372
- const unique = new Set(origins);
373
- if (unique.size !== origins.length) {
374
- throw artifactGraphTypeError(
375
- "artifact-graph-source-redirect-final-origin-duplicate",
376
- `Artifact graph file ${path} redirectFinalOrigins must be unique after canonicalization.`,
377
- );
378
- }
379
- return completeValue([...origins].sort(lexicalCompare));
380
- }
381
-
382
- function graphImmutableUrl(value, label, revision) {
383
- let url;
384
- try {
385
- url = immutableUrl(
386
- artifactGraphText(
387
- value,
388
- label,
389
- "artifact-graph-source-url-missing",
390
- ),
391
- label,
392
- );
393
- } catch (error) {
394
- if (ARTIFACT_ERRORS.has(error)) throw error;
395
- throw artifactGraphTypeError(
396
- "artifact-graph-source-url-mutable",
397
- `${label} must identify an immutable HTTPS or same-origin source authority.`,
398
- error,
399
- );
400
- }
401
- if (ARTIFACT_GRAPH_MUTABLE_SOURCE_PATTERN.test(new URL(url).pathname)) {
402
- throw artifactGraphTypeError(
403
- "artifact-graph-source-url-mutable",
404
- `${label} names a mutable branch, channel, or release alias.`,
405
- );
406
- }
407
- if (!url.toLowerCase().includes(revision.toLowerCase())) {
408
- throw artifactGraphTypeError(
409
- "artifact-graph-source-revision-unbound",
410
- `${label} must contain the file revision.`,
411
- );
412
- }
413
- return url;
414
- }
415
-
416
270
  function lexicalCompare(left, right) {
417
271
  return left < right ? -1 : left > right ? 1 : 0;
418
272
  }
419
273
 
420
- // Structural comparison for dormant authenticated-graph compatibility
421
- // normalizers only. Ordinary graph creation treats edges and transforms as
422
- // inert metadata and never calls these helpers. Do not enable them, including
423
- // for secure mode, without an explicit review with the user.
424
- function compatibilityRecordKey(value) {
425
- if (Array.isArray(value)) {
426
- return `[${value.map(compatibilityRecordKey).join(",")}]`;
427
- }
428
- if (value && typeof value === "object") {
429
- return `{${Object.keys(value).sort().map((key) =>
430
- `${JSON.stringify(key)}:${compatibilityRecordKey(value[key])}`).join(",")}}`;
431
- }
432
- return JSON.stringify(value);
433
- }
434
-
435
- function normalizeFile(value, kind, index, revision, secure) {
274
+ function normalizeFile(value, kind, index) {
436
275
  if (!value || typeof value !== "object" || Array.isArray(value)) {
437
276
  throw new TypeError(`${kind} file ${String(index)} must be an object.`);
438
277
  }
@@ -444,14 +283,7 @@ function normalizeFile(value, kind, index, revision, secure) {
444
283
  ) {
445
284
  throw new TypeError(`${kind} file path must be a normalized relative path.`);
446
285
  }
447
- const url = secure
448
- ? immutableUrl(value.url, `${kind} file url`)
449
- : ordinarySourceUrl(value.url, `${kind} file url`);
450
- if (secure && !url.toLowerCase().includes(revision.toLowerCase())) {
451
- throw new TypeError(
452
- `${kind} file URL must contain its caller-supplied revision.`,
453
- );
454
- }
286
+ const url = ordinarySourceUrl(value.url, `${kind} file url`);
455
287
  return completeValue({
456
288
  kind,
457
289
  index,
@@ -465,9 +297,8 @@ function normalizeFile(value, kind, index, revision, secure) {
465
297
  });
466
298
  }
467
299
 
468
- function uniqueFiles(files, label, kind, revision, {
300
+ function uniqueFiles(files, label, kind, {
469
301
  allowEmpty = false,
470
- secure = false,
471
302
  } = {}) {
472
303
  if (!Array.isArray(files) || (!allowEmpty && files.length < 1)) {
473
304
  throw new TypeError(
@@ -479,7 +310,7 @@ function uniqueFiles(files, label, kind, revision, {
479
310
  const paths = new Set();
480
311
  const urls = new Set();
481
312
  return completeValue(files.map((value, index) => {
482
- const file = normalizeFile(value, kind, index, revision, secure);
313
+ const file = normalizeFile(value, kind, index);
483
314
  if (paths.has(file.path) || urls.has(file.url)) {
484
315
  throw new TypeError(`${label} file paths and URLs must be unique.`);
485
316
  }
@@ -498,7 +329,7 @@ function publicFile(file) {
498
329
  return completeValue(result);
499
330
  }
500
331
 
501
- function normalizeArtifactGraphFile(value, index, secure = false) {
332
+ function normalizeArtifactGraphFile(value, index) {
502
333
  if (!value || typeof value !== "object" || Array.isArray(value)) {
503
334
  throw artifactGraphTypeError(
504
335
  "artifact-graph-file-descriptor-not-object",
@@ -526,19 +357,9 @@ function normalizeArtifactGraphFile(value, index, secure = false) {
526
357
  "artifact-graph-file-revision-missing",
527
358
  "artifact-graph-file-revision-length-exceeded",
528
359
  );
529
- const sourceUrl = secure
530
- ? graphImmutableUrl(
531
- value.sourceUrl ?? value.url,
532
- `Artifact graph file ${path} sourceUrl`,
533
- revision,
534
- )
535
- : ordinarySourceUrl(
536
- value.sourceUrl ?? value.url,
537
- `Artifact graph file ${path} sourceUrl`,
538
- );
539
- const redirectFinalOrigins = normalizeGraphRedirectFinalOrigins(
540
- value.redirectFinalOrigins,
541
- path,
360
+ const sourceUrl = ordinarySourceUrl(
361
+ value.sourceUrl ?? value.url,
362
+ `Artifact graph file ${path} sourceUrl`,
542
363
  );
543
364
  // Legal metadata belongs to the selected upstream distribution. Preserve a
544
365
  // caller-supplied value as inert metadata, but never require or interpret it
@@ -604,7 +425,6 @@ function normalizeArtifactGraphFile(value, index, secure = false) {
604
425
  mediaType,
605
426
  sourceMediaType,
606
427
  runtimeRequestUrls: completeValue(normalizedRequestUrls),
607
- redirectFinalOrigins,
608
428
  });
609
429
  }
610
430
 
@@ -620,36 +440,9 @@ function publicArtifactGraphFile(file) {
620
440
  ? {}
621
441
  : { sourceMediaType: file.sourceMediaType }),
622
442
  runtimeRequestUrls: file.runtimeRequestUrls,
623
- ...(file.redirectFinalOrigins.length < 1
624
- ? {}
625
- : { redirectFinalOrigins: file.redirectFinalOrigins }),
626
443
  });
627
444
  }
628
445
 
629
- function normalizeGraphOccurrence(value, label) {
630
- return graphPositiveInteger(
631
- value,
632
- `${label} occurrence`,
633
- "artifact-graph-edge-occurrence-positive-safe-integer-required",
634
- );
635
- }
636
-
637
- function normalizeGraphModulePath(value, label, filesByPath) {
638
- const path = canonicalArtifactPath(
639
- value,
640
- `${label} modulePath`,
641
- "artifact-graph-edge-module-path-missing",
642
- "artifact-graph-edge-module-path-noncanonical",
643
- );
644
- if (!ARTIFACT_GRAPH_JAVASCRIPT_KINDS.has(filesByPath.get(path)?.kind)) {
645
- throw artifactGraphTypeError(
646
- "artifact-graph-edge-module-path-not-runtime-javascript",
647
- `${label} modulePath must name one declared runtime JavaScript file.`,
648
- );
649
- }
650
- return path;
651
- }
652
-
653
446
  function normalizeGraphTargetPath(value, label, filesByPath, javascript = false) {
654
447
  const path = canonicalArtifactPath(
655
448
  value,
@@ -667,380 +460,6 @@ function normalizeGraphTargetPath(value, label, filesByPath, javascript = false)
667
460
  return path;
668
461
  }
669
462
 
670
- function normalizeGraphPolicy(value, label) {
671
- const policy = value ?? "artifact-targets-admitted";
672
- if (!ARTIFACT_GRAPH_EDGE_POLICIES.has(policy)) {
673
- throw artifactGraphTypeError(
674
- "artifact-graph-edge-policy-not-admitted",
675
- `${label} edgePolicy must identify an admitted artifact target or an inactive rejected runtime branch.`,
676
- );
677
- }
678
- return policy;
679
- }
680
-
681
- function normalizeGraphTargets(value, label, filesByPath, {
682
- javascript = false,
683
- worker = false,
684
- } = {}) {
685
- if (!Array.isArray(value)) {
686
- throw artifactGraphTypeError(
687
- "artifact-graph-edge-targets-not-array",
688
- `${label} targets must be an array.`,
689
- );
690
- }
691
- const allowedMatches = worker
692
- ? new Set([...ARTIFACT_GRAPH_IMPORT_MATCHES, "self-module-url"])
693
- : ARTIFACT_GRAPH_IMPORT_MATCHES;
694
- const targets = value.map((target, index) => {
695
- if (!target || typeof target !== "object" || Array.isArray(target)) {
696
- throw artifactGraphTypeError(
697
- "artifact-graph-edge-target-not-object",
698
- `${label} target ${String(index)} must be an object.`,
699
- );
700
- }
701
- const match = artifactGraphText(
702
- target.match,
703
- `${label} target ${String(index)} match`,
704
- "artifact-graph-edge-target-match-missing",
705
- );
706
- if (!allowedMatches.has(match)) {
707
- throw artifactGraphTypeError(
708
- "artifact-graph-edge-target-match-not-admitted",
709
- `${label} target ${String(index)} match is not admitted.`,
710
- );
711
- }
712
- const targetPath = normalizeGraphTargetPath(
713
- target.targetPath,
714
- `${label} target ${String(index)}`,
715
- filesByPath,
716
- javascript,
717
- );
718
- const exactSpecifier = match === "exact-runtime-specifier"
719
- ? artifactGraphText(
720
- target.exactSpecifier ?? target.specifier,
721
- `${label} target ${String(index)} exactSpecifier`,
722
- "artifact-graph-edge-target-specifier-missing",
723
- )
724
- : null;
725
- return completeValue({ match, targetPath, exactSpecifier });
726
- });
727
- targets.sort((left, right) =>
728
- lexicalCompare(compatibilityRecordKey(left), compatibilityRecordKey(right)));
729
- const identities = new Set(targets.map(compatibilityRecordKey));
730
- if (identities.size !== targets.length) {
731
- throw artifactGraphTypeError(
732
- "artifact-graph-edge-target-duplicate",
733
- `${label} targets must be unique.`,
734
- );
735
- }
736
- return completeValue(targets);
737
- }
738
-
739
- function normalizeArtifactGraphEdges(value, filesByPath, negativeRuntimeRequestUrls) {
740
- const edges = value ?? {};
741
- if (!edges || typeof edges !== "object" || Array.isArray(edges)) {
742
- throw artifactGraphTypeError(
743
- "artifact-graph-edges-not-object",
744
- "Artifact graph edges must be an object.",
745
- );
746
- }
747
- const allowedEdgeNames = new Set([
748
- "cacheOpens",
749
- "dynamicImports",
750
- "fetches",
751
- "moduleWorkers",
752
- "staticImports",
753
- ]);
754
- if (Reflect.ownKeys(edges).some((name) =>
755
- typeof name !== "string" || !allowedEdgeNames.has(name))) {
756
- throw artifactGraphTypeError(
757
- "artifact-graph-edge-kind-not-admitted",
758
- "Artifact graph edges contain an edge kind that is not admitted.",
759
- );
760
- }
761
-
762
- function normalizeArray(name, normalize) {
763
- const values = edges[name] ?? [];
764
- if (!Array.isArray(values)) {
765
- throw artifactGraphTypeError(
766
- "artifact-graph-edge-list-not-array",
767
- `Artifact graph ${name} must be an array.`,
768
- );
769
- }
770
- const normalized = values.map((edge, index) => {
771
- if (!edge || typeof edge !== "object" || Array.isArray(edge)) {
772
- throw artifactGraphTypeError(
773
- "artifact-graph-edge-not-object",
774
- `Artifact graph ${name}[${String(index)}] must be an object.`,
775
- );
776
- }
777
- const label = `Artifact graph ${name}[${String(index)}]`;
778
- const modulePath = normalizeGraphModulePath(edge.modulePath, label, filesByPath);
779
- const occurrence = normalizeGraphOccurrence(edge.occurrence, label);
780
- return normalize(edge, label, modulePath, occurrence);
781
- });
782
- normalized.sort((left, right) =>
783
- lexicalCompare(compatibilityRecordKey(left), compatibilityRecordKey(right)));
784
- const occurrences = new Set();
785
- for (const edge of normalized) {
786
- const key = `${edge.modulePath}\u0000${String(edge.occurrence)}`;
787
- if (occurrences.has(key)) {
788
- throw artifactGraphTypeError(
789
- "artifact-graph-edge-occurrence-duplicate",
790
- `Artifact graph ${name} contains a duplicate module occurrence.`,
791
- );
792
- }
793
- occurrences.add(key);
794
- }
795
- return completeValue(normalized);
796
- }
797
-
798
- const staticImports = normalizeArray(
799
- "staticImports",
800
- (edge, label, modulePath, occurrence) => completeValue({
801
- modulePath,
802
- occurrence,
803
- specifier: artifactGraphText(
804
- edge.specifier,
805
- `${label} specifier`,
806
- "artifact-graph-static-import-specifier-missing",
807
- ),
808
- targetPath: normalizeGraphTargetPath(
809
- edge.targetPath,
810
- label,
811
- filesByPath,
812
- true,
813
- ),
814
- }),
815
- );
816
- const dynamicImports = normalizeArray(
817
- "dynamicImports",
818
- (edge, label, modulePath, occurrence) => {
819
- const edgePolicy = normalizeGraphPolicy(edge.edgePolicy, label);
820
- const targets = normalizeGraphTargets(edge.targets ?? [], label, filesByPath, {
821
- javascript: true,
822
- });
823
- if (
824
- (edgePolicy === "artifact-targets-admitted") !== (targets.length > 0)
825
- ) {
826
- throw artifactGraphTypeError(
827
- "artifact-graph-dynamic-import-policy-target-mismatch",
828
- `${label} must have targets exactly when its edgePolicy admits artifact targets.`,
829
- );
830
- }
831
- return completeValue({ modulePath, occurrence, edgePolicy, targets });
832
- },
833
- );
834
- const moduleWorkers = normalizeArray(
835
- "moduleWorkers",
836
- (edge, label, modulePath, occurrence) => {
837
- const edgePolicy = normalizeGraphPolicy(edge.edgePolicy, label);
838
- const targets = normalizeGraphTargets(edge.targets ?? [], label, filesByPath, {
839
- javascript: true,
840
- worker: true,
841
- });
842
- if (
843
- (edgePolicy === "artifact-targets-admitted") !== (targets.length > 0)
844
- ) {
845
- throw artifactGraphTypeError(
846
- "artifact-graph-module-worker-policy-target-mismatch",
847
- `${label} must have targets exactly when its edgePolicy admits artifact targets.`,
848
- );
849
- }
850
- if (targets.some((target) =>
851
- target.match === "self-module-url" && target.targetPath !== modulePath)) {
852
- throw artifactGraphTypeError(
853
- "artifact-graph-module-worker-self-target-mismatch",
854
- `${label} self-module-url target must equal modulePath.`,
855
- );
856
- }
857
- return completeValue({ modulePath, occurrence, edgePolicy, targets });
858
- },
859
- );
860
- const fetches = normalizeArray(
861
- "fetches",
862
- (edge, label, modulePath, occurrence) => {
863
- const edgePolicy = normalizeGraphPolicy(edge.edgePolicy, label);
864
- const methods = edge.methods ?? ["GET"];
865
- if (
866
- !Array.isArray(methods)
867
- || methods.length !== 1
868
- || methods[0] !== "GET"
869
- ) {
870
- throw artifactGraphTypeError(
871
- "artifact-graph-fetch-method-not-get",
872
- `${label} methods must be exactly ["GET"].`,
873
- );
874
- }
875
- const targetPaths = edge.targetPaths ?? [];
876
- if (!Array.isArray(targetPaths)) {
877
- throw artifactGraphTypeError(
878
- "artifact-graph-fetch-targets-not-array",
879
- `${label} targetPaths must be an array.`,
880
- );
881
- }
882
- const normalizedTargetPaths = [...new Set(targetPaths.map((path) =>
883
- normalizeGraphTargetPath(path, label, filesByPath)))].sort();
884
- if (normalizedTargetPaths.length !== targetPaths.length) {
885
- throw artifactGraphTypeError(
886
- "artifact-graph-fetch-target-duplicate",
887
- `${label} targetPaths must be unique.`,
888
- );
889
- }
890
- if (normalizedTargetPaths.some((path) =>
891
- ARTIFACT_GRAPH_JAVASCRIPT_KINDS.has(filesByPath.get(path)?.kind))) {
892
- throw artifactGraphTypeError(
893
- "artifact-graph-fetch-javascript-target-rejected",
894
- `${label} must not expose authenticated JavaScript bytes through a fetch edge.`,
895
- );
896
- }
897
- const negativeUrls = edge.negativeRuntimeRequestUrls ?? [];
898
- if (!Array.isArray(negativeUrls)) {
899
- throw artifactGraphTypeError(
900
- "artifact-graph-fetch-negative-routes-not-array",
901
- `${label} negativeRuntimeRequestUrls must be an array.`,
902
- );
903
- }
904
- const normalizedNegativeUrls = [...new Set(negativeUrls.map((url, index) =>
905
- graphRuntimeRequestUrl(url, `${label} negativeRuntimeRequestUrls[${String(index)}]`)))].sort();
906
- if (
907
- normalizedNegativeUrls.length !== negativeUrls.length
908
- || normalizedNegativeUrls.some((url) => !negativeRuntimeRequestUrls.has(url))
909
- ) {
910
- throw artifactGraphTypeError(
911
- "artifact-graph-fetch-negative-route-undeclared",
912
- `${label} negative runtime request routes must be unique graph-level declarations.`,
913
- );
914
- }
915
- if (
916
- edgePolicy === "artifact-targets-admitted"
917
- && normalizedTargetPaths.length === 0
918
- && normalizedNegativeUrls.length === 0
919
- ) {
920
- throw artifactGraphTypeError(
921
- "artifact-graph-fetch-targets-incomplete",
922
- `${label} must admit at least one artifact or authenticated negative route.`,
923
- );
924
- }
925
- if (
926
- edgePolicy === "inactive-runtime-branch-rejected"
927
- && (normalizedTargetPaths.length > 0 || normalizedNegativeUrls.length > 0)
928
- ) {
929
- throw artifactGraphTypeError(
930
- "artifact-graph-fetch-policy-target-mismatch",
931
- `${label} rejected inactive branch must not name fetch targets.`,
932
- );
933
- }
934
- return completeValue({
935
- modulePath,
936
- occurrence,
937
- edgePolicy,
938
- methods: completeValue(["GET"]),
939
- targetPaths: completeValue(normalizedTargetPaths),
940
- negativeRuntimeRequestUrls: completeValue(normalizedNegativeUrls),
941
- allowMaterializedUrls: edge.allowMaterializedUrls === true,
942
- });
943
- },
944
- );
945
- const cacheOpens = normalizeArray(
946
- "cacheOpens",
947
- (edge, label, modulePath, occurrence) => {
948
- const edgePolicy = normalizeGraphPolicy(edge.edgePolicy, label);
949
- const cacheName = artifactGraphText(
950
- edge.cacheName,
951
- `${label} cacheName`,
952
- "artifact-graph-cache-name-missing",
953
- );
954
- const targetPaths = edge.targetPaths ?? [];
955
- if (!Array.isArray(targetPaths)) {
956
- throw artifactGraphTypeError(
957
- "artifact-graph-cache-targets-not-array",
958
- `${label} targetPaths must be an array.`,
959
- );
960
- }
961
- const normalizedTargetPaths = [...new Set(targetPaths.map((path) =>
962
- normalizeGraphTargetPath(path, label, filesByPath)))].sort();
963
- if (normalizedTargetPaths.length !== targetPaths.length) {
964
- throw artifactGraphTypeError(
965
- "artifact-graph-cache-target-duplicate",
966
- `${label} targetPaths must be unique.`,
967
- );
968
- }
969
- if (normalizedTargetPaths.some((path) =>
970
- ARTIFACT_GRAPH_JAVASCRIPT_KINDS.has(filesByPath.get(path)?.kind))) {
971
- throw artifactGraphTypeError(
972
- "artifact-graph-cache-javascript-target-rejected",
973
- `${label} must not expose authenticated JavaScript bytes through a cache edge.`,
974
- );
975
- }
976
- if (
977
- (edgePolicy === "artifact-targets-admitted") !== (normalizedTargetPaths.length > 0)
978
- ) {
979
- throw artifactGraphTypeError(
980
- "artifact-graph-cache-policy-target-mismatch",
981
- `${label} must have targets exactly when its edgePolicy admits authenticated cache reads.`,
982
- );
983
- }
984
- return completeValue({
985
- modulePath,
986
- occurrence,
987
- edgePolicy,
988
- cacheName,
989
- targetPaths: completeValue(normalizedTargetPaths),
990
- });
991
- },
992
- );
993
- return completeValue({
994
- staticImports,
995
- dynamicImports,
996
- moduleWorkers,
997
- fetches,
998
- cacheOpens,
999
- });
1000
- }
1001
-
1002
- function normalizeArtifactGraphTransforms(value, filesByPath) {
1003
- const transforms = value ?? [];
1004
- if (!Array.isArray(transforms)) {
1005
- throw artifactGraphTypeError(
1006
- "artifact-graph-transforms-not-array",
1007
- "Artifact graph transforms must be an array.",
1008
- );
1009
- }
1010
- const normalized = transforms.map((transform, index) => {
1011
- if (!transform || typeof transform !== "object" || Array.isArray(transform)) {
1012
- throw artifactGraphTypeError(
1013
- "artifact-graph-transform-not-object",
1014
- `Artifact graph transform ${String(index)} must be an object.`,
1015
- );
1016
- }
1017
- const label = `Artifact graph transform ${String(index)}`;
1018
- if (!["function-return-this-to-global-this", "typed-array-constructor"].includes(
1019
- transform.kind,
1020
- )) {
1021
- throw artifactGraphTypeError(
1022
- "artifact-graph-transform-kind-not-admitted",
1023
- `${label} kind is not admitted.`,
1024
- );
1025
- }
1026
- return completeValue({
1027
- kind: transform.kind,
1028
- modulePath: normalizeGraphModulePath(transform.modulePath, label, filesByPath),
1029
- occurrence: normalizeGraphOccurrence(transform.occurrence, label),
1030
- });
1031
- });
1032
- normalized.sort((left, right) =>
1033
- lexicalCompare(compatibilityRecordKey(left), compatibilityRecordKey(right)));
1034
- const identities = new Set(normalized.map(compatibilityRecordKey));
1035
- if (identities.size !== normalized.length) {
1036
- throw artifactGraphTypeError(
1037
- "artifact-graph-transform-occurrence-duplicate",
1038
- "Artifact graph transform occurrences must be unique.",
1039
- );
1040
- }
1041
- return completeValue(normalized);
1042
- }
1043
-
1044
463
  function normalizeArtifactGraphVoices(value, defaultVoice, filesByPath) {
1045
464
  if (!Array.isArray(value) || value.length < 1) {
1046
465
  throw artifactGraphTypeError(
@@ -1098,8 +517,6 @@ function artifactGraphProjection({
1098
517
  model,
1099
518
  runtime,
1100
519
  files,
1101
- edges,
1102
- transforms,
1103
520
  }) {
1104
521
  return completeValue({
1105
522
  protocol: BROWSER_SPEECH_ARTIFACT_GRAPH_PROTOCOL,
@@ -1109,8 +526,6 @@ function artifactGraphProjection({
1109
526
  model,
1110
527
  runtime,
1111
528
  files: completeValue(files.map((file) => publicArtifactGraphFile(file))),
1112
- edges,
1113
- transforms,
1114
529
  });
1115
530
  }
1116
531
 
@@ -1127,8 +542,6 @@ export function createBrowserSpeechArtifactGraph({
1127
542
  model,
1128
543
  runtime,
1129
544
  files,
1130
- edges,
1131
- transforms,
1132
545
  } = {}) {
1133
546
  if (kind !== ARTIFACT_GRAPH_KIND) {
1134
547
  throw artifactGraphTypeError(
@@ -1173,7 +586,7 @@ export function createBrowserSpeechArtifactGraph({
1173
586
  );
1174
587
  }
1175
588
  const normalizedFiles = files.map((file, index) =>
1176
- normalizeArtifactGraphFile(file, index, false));
589
+ normalizeArtifactGraphFile(file, index));
1177
590
  normalizedFiles.sort((left, right) => lexicalCompare(left.path, right.path));
1178
591
  const filesByPath = new Map();
1179
592
  const lowercasePaths = new Set();
@@ -1318,11 +731,6 @@ export function createBrowserSpeechArtifactGraph({
1318
731
  );
1319
732
  }
1320
733
 
1321
- // Negative-route admission belonged to the former authenticated graph. The
1322
- // ordinary materializer now routes known files and lets every unknown URL
1323
- // continue through the browser's native operation.
1324
- const normalizedNegativeRoutes = completeValue([]);
1325
-
1326
734
  const modelId = artifactGraphIdentifier(
1327
735
  model.id,
1328
736
  "Browser speech artifact graph model id",
@@ -1378,33 +786,6 @@ export function createBrowserSpeechArtifactGraph({
1378
786
  ? normalizeArtifactGraphVoices(model.voices, defaultVoice, filesByPath)
1379
787
  : completeValue([]);
1380
788
 
1381
- // Edge and transform declarations are retained only as inert compatibility
1382
- // metadata. Ordinary execution discovers routing from the complete file
1383
- // inventory and never admits or rejects runtime operations through them.
1384
- const edgeRecord = edges && typeof edges === "object" && !Array.isArray(edges)
1385
- ? edges
1386
- : {};
1387
- const normalizedEdges = completeValue({
1388
- staticImports: completeValue(Array.isArray(edgeRecord.staticImports)
1389
- ? edgeRecord.staticImports.map((edge) => completeValue({ ...edge }))
1390
- : []),
1391
- dynamicImports: completeValue(Array.isArray(edgeRecord.dynamicImports)
1392
- ? edgeRecord.dynamicImports.map((edge) => completeValue({ ...edge }))
1393
- : []),
1394
- moduleWorkers: completeValue(Array.isArray(edgeRecord.moduleWorkers)
1395
- ? edgeRecord.moduleWorkers.map((edge) => completeValue({ ...edge }))
1396
- : []),
1397
- fetches: completeValue(Array.isArray(edgeRecord.fetches)
1398
- ? edgeRecord.fetches.map((edge) => completeValue({ ...edge }))
1399
- : []),
1400
- cacheOpens: completeValue(Array.isArray(edgeRecord.cacheOpens)
1401
- ? edgeRecord.cacheOpens.map((edge) => completeValue({ ...edge }))
1402
- : []),
1403
- });
1404
- const normalizedTransforms = completeValue(Array.isArray(transforms)
1405
- ? transforms.map((transform) => completeValue({ ...transform }))
1406
- : []);
1407
-
1408
789
  const runtimeFiles = completeValue(normalizedFiles.filter((file) =>
1409
790
  file.kind.startsWith("runtime-")));
1410
791
  const modelFiles = completeValue(normalizedFiles.filter((file) =>
@@ -1448,7 +829,6 @@ export function createBrowserSpeechArtifactGraph({
1448
829
  wasmPath,
1449
830
  ...(numThreads === null ? {} : { numThreads }),
1450
831
  }),
1451
- negativeRuntimeRequestUrls: completeValue(normalizedNegativeRoutes),
1452
832
  });
1453
833
  const normalizedModel = completeValue({
1454
834
  id: modelId,
@@ -1466,8 +846,6 @@ export function createBrowserSpeechArtifactGraph({
1466
846
  model: normalizedModel,
1467
847
  runtime: normalizedRuntime,
1468
848
  files: normalizedFiles,
1469
- edges: normalizedEdges,
1470
- transforms: normalizedTransforms,
1471
849
  });
1472
850
  const graph = completeValue({
1473
851
  ...projection,
@@ -1482,8 +860,6 @@ export function createBrowserSpeechArtifactGraph({
1482
860
  modelFiles,
1483
861
  model: normalizedModel,
1484
862
  runtime: normalizedRuntime,
1485
- edges: normalizedEdges,
1486
- transforms: normalizedTransforms,
1487
863
  ...(normalizedSecurity ? { security: normalizedSecurity } : {}),
1488
864
  }));
1489
865
  return graph;
@@ -1524,11 +900,7 @@ export function createBrowserSpeechAuthority({
1524
900
  model.files ?? [],
1525
901
  "Browser speech model",
1526
902
  "model",
1527
- modelRevision,
1528
- {
1529
- allowEmpty: true,
1530
- secure: false,
1531
- },
903
+ { allowEmpty: true },
1532
904
  );
1533
905
  const runtimeAdapter = requiredText(runtime.adapter, "Browser speech runtime adapter");
1534
906
  const expectedAdapter = role === "stt"
@@ -1543,8 +915,6 @@ export function createBrowserSpeechAuthority({
1543
915
  runtime.files,
1544
916
  "Browser speech runtime",
1545
917
  "runtime",
1546
- runtimeRevision,
1547
- { secure: false },
1548
918
  );
1549
919
  const wasmPaths = runtime.wasmPaths === undefined
1550
920
  ? null
@@ -1708,7 +1078,6 @@ function storageNames(authority, files) {
1708
1078
  return completeValue({
1709
1079
  key: prefix,
1710
1080
  selection: `${prefix}.selection.json`,
1711
- legacyManifest: `${prefix}.complete.json`,
1712
1081
  files: completeValue(files.map((_, index) =>
1713
1082
  `${prefix}.${String(index).padStart(4, "0")}.artifact`)),
1714
1083
  });
@@ -1745,41 +1114,12 @@ async function* byteChunks(body, signal) {
1745
1114
  );
1746
1115
  }
1747
1116
 
1748
- // Runtime entry bytes use one deliberately closed capability grammar. The only
1749
- // module reference is import.meta and the only artifact transport is fetch(),
1750
- // which the Worker replaces with its admitted object-URL map before import.
1751
- // Executable strings, child execution contexts, script loaders, and alternate
1752
- // network transports are outside the grammar. Literal escape sequences are
1753
- // decoded before the same capability tokens are evaluated.
1754
- const CLOSED_MODULE_OUT_OF_GRAMMAR_IDENTIFIERS = new Set([
1755
- "AsyncFunction",
1756
- "AsyncGeneratorFunction",
1757
- "EventSource",
1758
- "Function",
1759
- "GeneratorFunction",
1760
- "RTCPeerConnection",
1761
- "SharedWorker",
1762
- "WebSocket",
1763
- "WebTransport",
1764
- "Worker",
1765
- "XMLHttpRequest",
1766
- "eval",
1767
- "importScripts",
1768
- ]);
1769
- const CLOSED_MODULE_OUT_OF_GRAMMAR_LITERAL =
1770
- /(?:^|[^A-Za-z0-9_$])(?:AsyncFunction|AsyncGeneratorFunction|EventSource|Function|GeneratorFunction|RTCPeerConnection|SharedWorker|WebSocket|WebTransport|Worker|XMLHttpRequest|constructor|eval|importScripts)(?:$|[^A-Za-z0-9_$])|(?:^|[^A-Za-z0-9_$])import\s*\(/u;
1771
-
1772
- function assertSelfContainedModuleSource(source, label) {
1117
+ function tokenizeArtifactGraphModule(source, modulePath) {
1118
+ const tokens = [];
1773
1119
  let index = 0;
1774
- let nextTemplateId = 1;
1775
- const templateStack = [];
1776
- const literalFragments = [];
1777
-
1778
- function fail() {
1779
- throw speechError(
1780
- "ARCANE_AI_RUNTIME_MODULE_GRAPH_UNDECLARED",
1781
- `${label} must be one self-contained JavaScript module without imports or re-exports.`,
1782
- );
1120
+
1121
+ function fail(reason, message) {
1122
+ throw artifactGraphError(reason, `${modulePath}: ${message}`);
1783
1123
  }
1784
1124
 
1785
1125
  function identifierStart(character) {
@@ -1790,316 +1130,10 @@ function assertSelfContainedModuleSource(source, label) {
1790
1130
  return /[A-Za-z0-9_$]/u.test(character ?? "");
1791
1131
  }
1792
1132
 
1793
- function assertLiteral(value) {
1794
- if (CLOSED_MODULE_OUT_OF_GRAMMAR_LITERAL.test(value)) fail();
1795
- }
1796
-
1797
- function assertComputedLiteral(value) {
1798
- if (value.includes("constructor") || /import\s*\(/u.test(value)) fail();
1799
- for (const identifier of CLOSED_MODULE_OUT_OF_GRAMMAR_IDENTIFIERS) {
1800
- if (value.includes(identifier)) fail();
1801
- }
1802
- }
1803
-
1804
- function recordLiteral(start, end, value) {
1805
- assertLiteral(value);
1806
- literalFragments.push(completeValue({
1807
- start,
1808
- end,
1809
- value,
1810
- templateIds: completeValue([...templateStack]),
1811
- }));
1812
- }
1813
-
1814
- function stripJoinerTrivia(value) {
1815
- return value
1816
- .replace(/\/\*[\s\S]*?\*\//gu, "")
1817
- .replace(/\/\/[^\r\n]*(?:\r?\n|$)/gu, "")
1818
- .replace(/\s+/gu, "");
1819
- }
1820
-
1821
- function sharesTemplate(left, right) {
1822
- return left.templateIds.some((id) => right.templateIds.includes(id));
1823
- }
1824
-
1825
- function staticallyJoins(left, right) {
1826
- const separator = stripJoinerTrivia(source.slice(left.end, right.start));
1827
- const usesConcat = separator.includes(".concat");
1828
- const withoutConcat = separator.replace(/\.concat/gu, "");
1829
- const usesPlus = withoutConcat.includes("+");
1830
- const usesTemplate = sharesTemplate(left, right)
1831
- && (withoutConcat.includes("${") || withoutConcat.includes("}"));
1832
- if (!usesConcat && !usesPlus && !usesTemplate) return false;
1833
- return (usesTemplate ? /^[+()${}]*$/u : /^[+()]*$/u).test(withoutConcat);
1834
- }
1835
-
1836
- function assertStaticLiteralChains() {
1837
- let chain = [];
1838
- function flushChain() {
1839
- if (chain.length > 1) {
1840
- assertComputedLiteral(chain.map((fragment) => fragment.value).join(""));
1841
- }
1842
- chain = [];
1843
- }
1844
- for (const fragment of literalFragments) {
1845
- const previous = chain[chain.length - 1];
1846
- if (previous && staticallyJoins(previous, fragment)) {
1847
- chain.push(fragment);
1848
- continue;
1849
- }
1850
- flushChain();
1851
- chain.push(fragment);
1852
- }
1853
- flushChain();
1854
- }
1855
-
1856
1133
  function readEscape() {
1857
- if (index >= source.length) fail();
1858
- const character = source[index];
1859
- index += 1;
1860
- if (character === "x") {
1861
- const hex = source.slice(index, index + 2);
1862
- if (!/^[a-f0-9]{2}$/iu.test(hex)) fail();
1863
- index += 2;
1864
- return String.fromCodePoint(Number.parseInt(hex, 16));
1865
- }
1866
- if (character === "u") {
1867
- if (source[index] === "{") {
1868
- const end = source.indexOf("}", index + 1);
1869
- if (end < 0) fail();
1870
- const hex = source.slice(index + 1, end);
1871
- if (!/^[a-f0-9]{1,6}$/iu.test(hex)) fail();
1872
- const codePoint = Number.parseInt(hex, 16);
1873
- if (codePoint > 0x10ffff) fail();
1874
- index = end + 1;
1875
- return String.fromCodePoint(codePoint);
1876
- }
1877
- const hex = source.slice(index, index + 4);
1878
- if (!/^[a-f0-9]{4}$/iu.test(hex)) fail();
1879
- index += 4;
1880
- return String.fromCodePoint(Number.parseInt(hex, 16));
1881
- }
1882
- if (character === "\n") return "";
1883
- if (character === "\r") {
1884
- if (source[index] === "\n") index += 1;
1885
- return "";
1886
- }
1887
- return completeValue({
1888
- "0": "\0",
1889
- b: "\b",
1890
- f: "\f",
1891
- n: "\n",
1892
- r: "\r",
1893
- t: "\t",
1894
- v: "\v",
1895
- })[character] ?? character;
1896
- }
1897
-
1898
- function readQuoted(quote) {
1899
- const start = index;
1900
- let value = "";
1901
- index += 1;
1902
- while (index < source.length) {
1903
- const character = source[index];
1904
- index += 1;
1905
- if (character === "\\") {
1906
- value += readEscape();
1907
- continue;
1908
- }
1909
- if (character === quote) {
1910
- recordLiteral(start, index, value);
1911
- return;
1912
- }
1913
- if (character === "\n" || character === "\r") fail();
1914
- value += character;
1915
- }
1916
- fail();
1917
- }
1918
-
1919
- function skipRegex() {
1920
- index += 1;
1921
- let inClass = false;
1922
- while (index < source.length) {
1923
- const character = source[index];
1924
- index += 1;
1925
- if (character === "\\") {
1926
- index += 1;
1927
- continue;
1928
- }
1929
- if (character === "[") inClass = true;
1930
- else if (character === "]") inClass = false;
1931
- else if (character === "/" && !inClass) {
1932
- while (/[A-Za-z]/u.test(source[index] ?? "")) index += 1;
1933
- return;
1934
- } else if (character === "\n" || character === "\r") {
1935
- fail();
1936
- }
1937
- }
1938
- fail();
1939
- }
1940
-
1941
- function canStartRegex(lastToken) {
1942
- return lastToken === null
1943
- || [
1944
- "(", "[", "{", "=", ":", ",", ";", "!", "?",
1945
- "&&", "||", "=>", "return", "case", "throw",
1946
- ].includes(lastToken);
1947
- }
1948
-
1949
- function readTemplate() {
1950
- const templateId = nextTemplateId;
1951
- nextTemplateId += 1;
1952
- templateStack.push(templateId);
1953
- let fragmentStart = index;
1954
- let value = "";
1955
- index += 1;
1956
- while (index < source.length) {
1957
- const character = source[index];
1958
- index += 1;
1959
- if (character === "\\") {
1960
- value += readEscape();
1961
- continue;
1962
- }
1963
- if (character === "`") {
1964
- recordLiteral(fragmentStart, index, value);
1965
- templateStack.pop();
1966
- return;
1967
- }
1968
- if (character === "$" && source[index] === "{") {
1969
- recordLiteral(fragmentStart, index - 1, value);
1970
- value = "";
1971
- index += 1;
1972
- scanCode(true);
1973
- fragmentStart = index;
1974
- continue;
1975
- }
1976
- value += character;
1977
- }
1978
- fail();
1979
- }
1980
-
1981
- function scanCode(stopAtTemplateBrace = false) {
1982
- let nestedBraces = 0;
1983
- let lastToken = null;
1984
- while (index < source.length) {
1985
- const character = source[index];
1986
- const next = source[index + 1];
1987
- if (/\s/u.test(character)) {
1988
- index += 1;
1989
- continue;
1990
- }
1991
- if (character === "/" && next === "/") {
1992
- index += 2;
1993
- while (index < source.length && source[index] !== "\n") index += 1;
1994
- continue;
1995
- }
1996
- if (character === "/" && next === "*") {
1997
- const end = source.indexOf("*/", index + 2);
1998
- if (end < 0) fail();
1999
- index = end + 2;
2000
- continue;
2001
- }
2002
- if (character === "'" || character === '"') {
2003
- if (lastToken === "from") fail();
2004
- readQuoted(character);
2005
- lastToken = "literal";
2006
- continue;
2007
- }
2008
- if (character === "`") {
2009
- if (lastToken === "from") fail();
2010
- readTemplate();
2011
- lastToken = "literal";
2012
- continue;
2013
- }
2014
- if (character === "/" && canStartRegex(lastToken)) {
2015
- skipRegex();
2016
- lastToken = "literal";
2017
- continue;
2018
- }
2019
- if (identifierStart(character)) {
2020
- const start = index;
2021
- index += 1;
2022
- while (identifierPart(source[index])) index += 1;
2023
- const word = source.slice(start, index);
2024
- if (CLOSED_MODULE_OUT_OF_GRAMMAR_IDENTIFIERS.has(word)) fail();
2025
- if (word === "constructor" && lastToken === ".") fail();
2026
- if (word === "import") {
2027
- while (/\s/u.test(source[index] ?? "")) index += 1;
2028
- if (source[index] === "." && source.slice(index + 1, index + 5) === "meta") {
2029
- index += 5;
2030
- lastToken = "import.meta";
2031
- continue;
2032
- }
2033
- fail();
2034
- }
2035
- lastToken = word;
2036
- continue;
2037
- }
2038
- if (character === "\\") fail();
2039
- if (stopAtTemplateBrace && character === "}") {
2040
- if (nestedBraces === 0) {
2041
- index += 1;
2042
- return;
2043
- }
2044
- nestedBraces -= 1;
2045
- } else if (stopAtTemplateBrace && character === "{") {
2046
- nestedBraces += 1;
2047
- }
2048
- const twoCharacters = `${character}${next ?? ""}`;
2049
- if (["&&", "||", "=>"].includes(twoCharacters)) {
2050
- lastToken = twoCharacters;
2051
- index += 2;
2052
- } else {
2053
- lastToken = character;
2054
- index += 1;
2055
- }
2056
- }
2057
- if (stopAtTemplateBrace) fail();
2058
- }
2059
-
2060
- scanCode();
2061
- assertStaticLiteralChains();
2062
- }
2063
-
2064
- // Dormant hardening retained for future review only. Ordinary speech artifact
2065
- // preparation never calls this closed-module inspection, and it must not be
2066
- // enabled for secure mode without an explicit review with the user.
2067
- async function assertSelfContainedRuntime(admitted, metadata) {
2068
- const javascriptFiles = admitted.files.filter(({ descriptor }) =>
2069
- descriptor.kind === "runtime" && descriptor.mediaType === "text/javascript");
2070
- if (
2071
- javascriptFiles.length !== 1
2072
- || javascriptFiles[0].descriptor.path !== metadata.runtime.entry
2073
- ) {
2074
- throw speechError(
2075
- "ARCANE_AI_RUNTIME_MODULE_GRAPH_UNDECLARED",
2076
- "Browser speech requires exactly one admitted self-contained runtime module.",
2077
- );
2078
- }
2079
- const [{ descriptor, file }] = javascriptFiles;
2080
- void file;
2081
- }
2082
-
2083
- function tokenizeArtifactGraphModule(source, modulePath) {
2084
- const tokens = [];
2085
- let index = 0;
2086
-
2087
- function fail(reason, message) {
2088
- throw artifactGraphError(reason, `${modulePath}: ${message}`);
2089
- }
2090
-
2091
- function identifierStart(character) {
2092
- return /[A-Za-z_$]/u.test(character ?? "");
2093
- }
2094
-
2095
- function identifierPart(character) {
2096
- return /[A-Za-z0-9_$]/u.test(character ?? "");
2097
- }
2098
-
2099
- function readEscape() {
2100
- if (index >= source.length) {
2101
- fail("artifact-graph-javascript-escape-unterminated", "unterminated escape sequence.");
2102
- }
1134
+ if (index >= source.length) {
1135
+ fail("artifact-graph-javascript-escape-unterminated", "unterminated escape sequence.");
1136
+ }
2103
1137
  const character = source[index];
2104
1138
  index += 1;
2105
1139
  if (character === "x") {
@@ -2304,694 +1338,6 @@ function tokenizeArtifactGraphModule(source, modulePath) {
2304
1338
  return completeValue(tokens);
2305
1339
  }
2306
1340
 
2307
- function artifactGraphDeclarationsByModule(values) {
2308
- const result = new Map();
2309
- for (const value of values) {
2310
- const entries = result.get(value.modulePath) ?? [];
2311
- entries.push(value);
2312
- result.set(value.modulePath, entries);
2313
- }
2314
- for (const entries of result.values()) {
2315
- entries.sort((left, right) => left.occurrence - right.occurrence);
2316
- }
2317
- return result;
2318
- }
2319
-
2320
- function assertArtifactGraphOccurrences(observed, declared, modulePath, subject) {
2321
- if (observed.length !== declared.length) {
2322
- throw artifactGraphError(
2323
- observed.length > declared.length
2324
- ? "artifact-graph-runtime-edge-undeclared"
2325
- : "artifact-graph-runtime-edge-declaration-unmatched",
2326
- `${modulePath} exposes ${String(observed.length)} ${subject} occurrence(s), but the graph declares ${String(declared.length)}.`,
2327
- );
2328
- }
2329
- for (let index = 0; index < declared.length; index += 1) {
2330
- if (declared[index].occurrence !== index + 1) {
2331
- throw artifactGraphError(
2332
- "artifact-graph-runtime-edge-occurrence-noncanonical",
2333
- `${modulePath} ${subject} declarations must use contiguous one-based occurrence values.`,
2334
- );
2335
- }
2336
- }
2337
- }
2338
-
2339
- function inspectArtifactGraphModuleSource(source, modulePath, metadata, {
2340
- strict = false,
2341
- } = {}) {
2342
- const tokens = tokenizeArtifactGraphModule(source, modulePath);
2343
- const staticImports = [];
2344
- const dynamicImports = [];
2345
- const fetches = [];
2346
- const moduleWorkers = [];
2347
- const cacheOpens = [];
2348
- const returnThisTransforms = [];
2349
- const typedArrayConstructors = [];
2350
- const warnings = new Set();
2351
- const forbiddenDynamicCode = new Set([
2352
- "AsyncFunction",
2353
- "AsyncGeneratorFunction",
2354
- "BroadcastChannel",
2355
- "GeneratorFunction",
2356
- "RTCPeerConnection",
2357
- "ShadowRealm",
2358
- "eval",
2359
- "importScripts",
2360
- "WebSocketStream",
2361
- ]);
2362
-
2363
- function next(index, offset = 1) {
2364
- return tokens[index + offset] ?? null;
2365
- }
2366
-
2367
- function previous(index, offset = 1) {
2368
- return tokens[index - offset] ?? null;
2369
- }
2370
-
2371
- function recordGuardCall(target, index, kind) {
2372
- const token = tokens[index];
2373
- const opening = next(index);
2374
- if (opening?.value !== "(") {
2375
- throw artifactGraphError(
2376
- `artifact-graph-runtime-${kind.toLowerCase()}-direct-call-required`,
2377
- `${modulePath} references ${kind} outside an admitted direct call boundary.`,
2378
- );
2379
- }
2380
- let start = token.start;
2381
- if (previous(index)?.value === ".") {
2382
- if (!["globalThis", "self"].includes(previous(index, 2)?.value)) {
2383
- throw artifactGraphError(
2384
- `artifact-graph-runtime-${kind.toLowerCase()}-receiver-not-global`,
2385
- `${modulePath} calls ${kind} through a non-global receiver.`,
2386
- );
2387
- }
2388
- start = previous(index, 2).start;
2389
- }
2390
- target.push(completeValue({ start, end: opening.end }));
2391
- }
2392
-
2393
- function typedArrayConstructor(index) {
2394
- const opening = next(index);
2395
- if (opening?.value !== "(") return null;
2396
- const property = previous(index, 2);
2397
- if (property?.type !== "identifier") return null;
2398
- if (previous(index, 3)?.value === "new") {
2399
- return completeValue({
2400
- start: property.start,
2401
- end: tokens[index].end,
2402
- receiver: source.slice(property.start, property.end),
2403
- });
2404
- }
2405
- if (
2406
- previous(index, 3)?.value === "."
2407
- && previous(index, 4)?.value === "]"
2408
- && previous(index, 5)?.value === "0"
2409
- && previous(index, 6)?.value === "["
2410
- && previous(index, 7)?.type === "identifier"
2411
- && previous(index, 8)?.value === "new"
2412
- ) {
2413
- return completeValue({
2414
- start: previous(index, 7).start,
2415
- end: tokens[index].end,
2416
- receiver: source.slice(previous(index, 7).start, property.end),
2417
- });
2418
- }
2419
- return null;
2420
- }
2421
-
2422
- for (let index = 0; index < tokens.length; index += 1) {
2423
- const token = tokens[index];
2424
- if (
2425
- (token.type === "identifier" || token.type === "string")
2426
- && token.value === ARTIFACT_GRAPH_GUARDS
2427
- ) {
2428
- throw artifactGraphError(
2429
- "artifact-graph-runtime-guard-reference-reserved",
2430
- `${modulePath} references the SDK-owned artifact graph runtime guard name.`,
2431
- );
2432
- }
2433
- if (
2434
- token.type === "string"
2435
- && [
2436
- "Function",
2437
- "BroadcastChannel",
2438
- "RTCPeerConnection",
2439
- "ShadowRealm",
2440
- "SharedWorker",
2441
- "Worker",
2442
- "WebSocketStream",
2443
- "XMLHttpRequest",
2444
- "constructor",
2445
- "eval",
2446
- "fetch",
2447
- "importScripts",
2448
- ].includes(token.value)
2449
- && previous(index)?.value === "["
2450
- && next(index)?.value === "]"
2451
- ) {
2452
- if (strict) {
2453
- throw artifactGraphError(
2454
- "artifact-graph-runtime-computed-dynamic-code-undeclared",
2455
- `${modulePath} contains computed access to dynamic code capability ${token.value}.`,
2456
- );
2457
- }
2458
- warnings.add(token.value);
2459
- continue;
2460
- }
2461
- if (token.type !== "identifier") continue;
2462
- if (forbiddenDynamicCode.has(token.value)) {
2463
- if (strict) {
2464
- throw artifactGraphError(
2465
- "artifact-graph-runtime-dynamic-code-undeclared",
2466
- `${modulePath} contains dynamic code capability ${token.value}, which is not admitted.`,
2467
- );
2468
- }
2469
- warnings.add(token.value);
2470
- continue;
2471
- }
2472
- if (token.value === "Function") {
2473
- const sequence = [
2474
- next(index)?.value,
2475
- next(index, 2)?.value,
2476
- next(index, 3)?.value,
2477
- next(index, 4)?.value,
2478
- next(index, 5)?.value,
2479
- ];
2480
- if (
2481
- [".", "?."].includes(previous(index)?.value)
2482
- || previous(index)?.value === "new"
2483
- || sequence[0] !== "("
2484
- || next(index, 2)?.type !== "string"
2485
- || sequence[1].trim() !== "return this"
2486
- || sequence[2] !== ")"
2487
- || sequence[3] !== "("
2488
- || sequence[4] !== ")"
2489
- ) {
2490
- if (strict) {
2491
- throw artifactGraphError(
2492
- "artifact-graph-runtime-dynamic-code-undeclared",
2493
- `${modulePath} contains a Function constructor outside the sole supported global-object transform.`,
2494
- );
2495
- }
2496
- warnings.add("Function");
2497
- continue;
2498
- }
2499
- returnThisTransforms.push(completeValue({
2500
- start: token.start,
2501
- end: next(index, 5).end,
2502
- }));
2503
- index += 5;
2504
- continue;
2505
- }
2506
- if (
2507
- token.value === "caches"
2508
- && next(index)?.value === "."
2509
- && next(index, 2)?.value === "open"
2510
- && next(index, 3)?.value === "("
2511
- ) {
2512
- let start = token.start;
2513
- if (previous(index)?.value === ".") {
2514
- if (!["globalThis", "self"].includes(previous(index, 2)?.value)) {
2515
- throw artifactGraphError(
2516
- "artifact-graph-runtime-cache-open-receiver-not-global",
2517
- `${modulePath} calls CacheStorage.open through a non-global receiver.`,
2518
- );
2519
- }
2520
- start = previous(index, 2).start;
2521
- }
2522
- cacheOpens.push(completeValue({ start, end: next(index, 3).end }));
2523
- continue;
2524
- }
2525
- if (token.value === "caches") {
2526
- if (previous(index)?.value === "typeof") continue;
2527
- throw artifactGraphError(
2528
- "artifact-graph-runtime-cache-open-direct-call-required",
2529
- `${modulePath} references CacheStorage outside an admitted direct open call.`,
2530
- );
2531
- }
2532
- if (
2533
- token.value === "constructor"
2534
- && [".", "?."].includes(previous(index)?.value)
2535
- && next(index)?.value === "("
2536
- ) {
2537
- const observed = previous(index)?.value === "." ? typedArrayConstructor(index) : null;
2538
- if (!observed) {
2539
- throw artifactGraphError(
2540
- "artifact-graph-runtime-constructor-dynamic-code-undeclared",
2541
- `${modulePath} calls a constructor property outside the declared typed-array constructor transform.`,
2542
- );
2543
- }
2544
- typedArrayConstructors.push(observed);
2545
- continue;
2546
- }
2547
- if (token.value === "import") {
2548
- if (next(index)?.value === "." && next(index, 2)?.value === "meta") {
2549
- index += 2;
2550
- continue;
2551
- }
2552
- if (next(index)?.value === "(") {
2553
- dynamicImports.push(completeValue({ start: token.start, end: next(index).end }));
2554
- continue;
2555
- }
2556
- let specifier = next(index)?.type === "string" ? next(index) : null;
2557
- if (!specifier) {
2558
- for (let cursor = index + 1; cursor < tokens.length; cursor += 1) {
2559
- if (tokens[cursor].value === ";") break;
2560
- if (tokens[cursor].value === "from" && next(cursor)?.type === "string") {
2561
- specifier = next(cursor);
2562
- break;
2563
- }
2564
- }
2565
- }
2566
- if (!specifier) {
2567
- throw artifactGraphError(
2568
- "artifact-graph-static-import-specifier-unresolved",
2569
- `${modulePath} contains a static import without one literal specifier.`,
2570
- );
2571
- }
2572
- staticImports.push(completeValue({
2573
- start: specifier.start,
2574
- end: specifier.end,
2575
- specifier: specifier.value,
2576
- }));
2577
- continue;
2578
- }
2579
- if (token.value === "export") {
2580
- if (!["*", "{"].includes(next(index)?.value)) continue;
2581
- let specifier = null;
2582
- for (let cursor = index + 1; cursor < tokens.length; cursor += 1) {
2583
- if (tokens[cursor].value === ";") break;
2584
- if (tokens[cursor].value === "from" && next(cursor)?.type === "string") {
2585
- specifier = next(cursor);
2586
- break;
2587
- }
2588
- if (["export", "import"].includes(tokens[cursor].value)) break;
2589
- }
2590
- if (specifier) {
2591
- staticImports.push(completeValue({
2592
- start: specifier.start,
2593
- end: specifier.end,
2594
- specifier: specifier.value,
2595
- }));
2596
- }
2597
- continue;
2598
- }
2599
- if (token.value === "fetch") {
2600
- recordGuardCall(fetches, index, "fetch");
2601
- continue;
2602
- }
2603
- if (token.value === "Worker") {
2604
- const opening = next(index);
2605
- if (opening?.value !== "(") {
2606
- if (strict) {
2607
- throw artifactGraphError(
2608
- "artifact-graph-runtime-worker-constructor-call-required",
2609
- `${modulePath} references Worker outside an admitted constructor boundary.`,
2610
- );
2611
- }
2612
- warnings.add("Worker");
2613
- continue;
2614
- }
2615
- let start = token.start;
2616
- if (previous(index)?.value === "new") {
2617
- start = previous(index).start;
2618
- } else if (previous(index)?.value === ".") {
2619
- if (!["globalThis", "self"].includes(previous(index, 2)?.value)) {
2620
- if (strict) {
2621
- throw artifactGraphError(
2622
- "artifact-graph-runtime-worker-receiver-not-global",
2623
- `${modulePath} constructs Worker through a non-global receiver.`,
2624
- );
2625
- }
2626
- warnings.add("Worker");
2627
- continue;
2628
- }
2629
- start = previous(index, 2).start;
2630
- if (previous(index, 3)?.value === "new") start = previous(index, 3).start;
2631
- }
2632
- moduleWorkers.push(completeValue({ start, end: opening.end }));
2633
- }
2634
- }
2635
-
2636
- const moduleTransforms = artifactGraphDeclarationsByModule(metadata.transforms)
2637
- .get(modulePath) ?? [];
2638
- const declarations = {
2639
- staticImports: artifactGraphDeclarationsByModule(metadata.edges.staticImports)
2640
- .get(modulePath) ?? [],
2641
- dynamicImports: artifactGraphDeclarationsByModule(metadata.edges.dynamicImports)
2642
- .get(modulePath) ?? [],
2643
- fetches: artifactGraphDeclarationsByModule(metadata.edges.fetches)
2644
- .get(modulePath) ?? [],
2645
- moduleWorkers: artifactGraphDeclarationsByModule(metadata.edges.moduleWorkers)
2646
- .get(modulePath) ?? [],
2647
- cacheOpens: artifactGraphDeclarationsByModule(metadata.edges.cacheOpens)
2648
- .get(modulePath) ?? [],
2649
- returnThisTransforms: moduleTransforms.filter((transform) =>
2650
- transform.kind === "function-return-this-to-global-this"),
2651
- typedArrayConstructors: moduleTransforms.filter((transform) =>
2652
- transform.kind === "typed-array-constructor"),
2653
- };
2654
- assertArtifactGraphOccurrences(
2655
- staticImports,
2656
- declarations.staticImports,
2657
- modulePath,
2658
- "static import or re-export",
2659
- );
2660
- assertArtifactGraphOccurrences(
2661
- dynamicImports,
2662
- declarations.dynamicImports,
2663
- modulePath,
2664
- "dynamic import",
2665
- );
2666
- assertArtifactGraphOccurrences(fetches, declarations.fetches, modulePath, "fetch");
2667
- assertArtifactGraphOccurrences(
2668
- moduleWorkers,
2669
- declarations.moduleWorkers,
2670
- modulePath,
2671
- "module Worker",
2672
- );
2673
- assertArtifactGraphOccurrences(
2674
- cacheOpens,
2675
- declarations.cacheOpens,
2676
- modulePath,
2677
- "CacheStorage open",
2678
- );
2679
- assertArtifactGraphOccurrences(
2680
- returnThisTransforms,
2681
- declarations.returnThisTransforms,
2682
- modulePath,
2683
- "Function return-this transform",
2684
- );
2685
- assertArtifactGraphOccurrences(
2686
- typedArrayConstructors,
2687
- declarations.typedArrayConstructors,
2688
- modulePath,
2689
- "typed-array constructor transform",
2690
- );
2691
- for (let index = 0; index < staticImports.length; index += 1) {
2692
- if (staticImports[index].specifier !== declarations.staticImports[index].specifier) {
2693
- throw artifactGraphError(
2694
- "artifact-graph-static-import-specifier-mismatch",
2695
- `${modulePath} static import occurrence ${String(index + 1)} does not match its declared specifier.`,
2696
- );
2697
- }
2698
- }
2699
- return completeValue({
2700
- source,
2701
- staticImports: completeValue(staticImports),
2702
- dynamicImports: completeValue(dynamicImports),
2703
- fetches: completeValue(fetches),
2704
- moduleWorkers: completeValue(moduleWorkers),
2705
- cacheOpens: completeValue(cacheOpens),
2706
- returnThisTransforms: completeValue(returnThisTransforms),
2707
- typedArrayConstructors: completeValue(typedArrayConstructors),
2708
- warnings: completeValue([...warnings].sort()),
2709
- declarations,
2710
- });
2711
- }
2712
-
2713
- function assertArtifactGraphStaticImportClosure(metadata) {
2714
- const dependencies = new Map(metadata.runtimeFiles
2715
- .filter((file) => ARTIFACT_GRAPH_JAVASCRIPT_KINDS.has(file.kind))
2716
- .map((file) => [file.path, []]));
2717
- for (const edge of metadata.edges.staticImports) {
2718
- dependencies.get(edge.modulePath).push(edge.targetPath);
2719
- }
2720
- const visiting = new Set();
2721
- const visited = new Set();
2722
- const order = [];
2723
- function visit(path) {
2724
- if (visiting.has(path)) {
2725
- throw artifactGraphError(
2726
- "artifact-graph-runtime-static-import-cycle",
2727
- `Artifact graph static imports contain a cycle at ${path}.`,
2728
- );
2729
- }
2730
- if (visited.has(path)) return;
2731
- visiting.add(path);
2732
- for (const dependency of dependencies.get(path) ?? []) visit(dependency);
2733
- visiting.delete(path);
2734
- visited.add(path);
2735
- order.push(path);
2736
- }
2737
- for (const path of [...dependencies.keys()].sort()) visit(path);
2738
- return completeValue(order);
2739
- }
2740
-
2741
- // Dormant hardening retained for future review only. Ordinary materialization
2742
- // uses the permissive router below; these declaration, capability, and closed
2743
- // inspection controls must not be enabled without explicit user review.
2744
- async function inspectArtifactGraphRuntime(admitted, metadata, signal) {
2745
- const admittedByPath = new Map(admitted.files.map((entry) => [entry.descriptor.path, entry]));
2746
- const plans = new Map();
2747
- for (const descriptor of metadata.runtimeFiles) {
2748
- throwIfAborted(signal);
2749
- if (!ARTIFACT_GRAPH_JAVASCRIPT_KINDS.has(descriptor.kind)) continue;
2750
- const file = admittedByPath.get(descriptor.path)?.file;
2751
- if (!file) {
2752
- throw artifactGraphError(
2753
- "artifact-graph-runtime-javascript-file-missing",
2754
- `Artifact graph runtime JavaScript file ${descriptor.path} is unavailable.`,
2755
- );
2756
- }
2757
- let source;
2758
- try {
2759
- const bytes = new Uint8Array(await file.arrayBuffer());
2760
- source = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
2761
- } catch (error) {
2762
- throw artifactGraphError(
2763
- "artifact-graph-runtime-javascript-utf8-decode-rejected",
2764
- `Artifact graph runtime JavaScript file ${descriptor.path} is not valid UTF-8.`,
2765
- error,
2766
- );
2767
- }
2768
- plans.set(
2769
- descriptor.path,
2770
- inspectArtifactGraphModuleSource(source, descriptor.path, metadata, {
2771
- strict: false,
2772
- }),
2773
- );
2774
- }
2775
- const order = assertArtifactGraphStaticImportClosure(metadata);
2776
- const warnings = [...new Set([...plans.values()].flatMap((plan) => plan.warnings))]
2777
- .sort();
2778
- throwIfAborted(signal);
2779
- return completeValue({ plans, order, warnings: completeValue(warnings) });
2780
- }
2781
-
2782
- function assertArtifactGraphRuntimeInspection(inspection) {
2783
- if (
2784
- !inspection
2785
- || !(inspection.plans instanceof Map)
2786
- || !Array.isArray(inspection.order)
2787
- || !Array.isArray(inspection.warnings)
2788
- ) {
2789
- throw artifactGraphError(
2790
- "artifact-graph-runtime-inspection-missing",
2791
- "Artifact graph runtime inspection is required before executable materialization.",
2792
- );
2793
- }
2794
- return inspection;
2795
- }
2796
-
2797
- function applyArtifactGraphModuleTransforms(plan, materializedByPath, guardCapability) {
2798
- const replacements = [];
2799
- for (let index = 0; index < plan.staticImports.length; index += 1) {
2800
- const observed = plan.staticImports[index];
2801
- const declared = plan.declarations.staticImports[index];
2802
- const targetUrl = materializedByPath.get(declared.targetPath)?.moduleUrl;
2803
- if (!targetUrl) {
2804
- throw artifactGraphError(
2805
- "artifact-graph-static-import-target-unmaterialized",
2806
- `Static import target ${declared.targetPath} was not materialized before ${declared.modulePath}.`,
2807
- );
2808
- }
2809
- replacements.push({
2810
- start: observed.start,
2811
- end: observed.end,
2812
- value: JSON.stringify(targetUrl),
2813
- });
2814
- }
2815
- for (let index = 0; index < plan.dynamicImports.length; index += 1) {
2816
- const observed = plan.dynamicImports[index];
2817
- const declared = plan.declarations.dynamicImports[index];
2818
- replacements.push({
2819
- start: observed.start,
2820
- end: observed.end,
2821
- value: `globalThis.${ARTIFACT_GRAPH_GUARDS}.dynamicImport(${JSON.stringify(guardCapability)},${JSON.stringify(declared.modulePath)},${String(declared.occurrence)},`,
2822
- });
2823
- }
2824
- for (let index = 0; index < plan.fetches.length; index += 1) {
2825
- const observed = plan.fetches[index];
2826
- const declared = plan.declarations.fetches[index];
2827
- replacements.push({
2828
- start: observed.start,
2829
- end: observed.end,
2830
- value: `globalThis.${ARTIFACT_GRAPH_GUARDS}.fetch(${JSON.stringify(guardCapability)},${JSON.stringify(declared.modulePath)},${String(declared.occurrence)},`,
2831
- });
2832
- }
2833
- for (let index = 0; index < plan.moduleWorkers.length; index += 1) {
2834
- const observed = plan.moduleWorkers[index];
2835
- const declared = plan.declarations.moduleWorkers[index];
2836
- replacements.push({
2837
- start: observed.start,
2838
- end: observed.end,
2839
- value: `globalThis.${ARTIFACT_GRAPH_GUARDS}.createWorker(${JSON.stringify(guardCapability)},${JSON.stringify(declared.modulePath)},${String(declared.occurrence)},`,
2840
- });
2841
- }
2842
- for (let index = 0; index < plan.cacheOpens.length; index += 1) {
2843
- const observed = plan.cacheOpens[index];
2844
- const declared = plan.declarations.cacheOpens[index];
2845
- replacements.push({
2846
- start: observed.start,
2847
- end: observed.end,
2848
- value: `globalThis.${ARTIFACT_GRAPH_GUARDS}.openCache(${JSON.stringify(guardCapability)},${JSON.stringify(declared.modulePath)},${String(declared.occurrence)},`,
2849
- });
2850
- }
2851
- for (const observed of plan.returnThisTransforms) {
2852
- replacements.push({ start: observed.start, end: observed.end, value: "globalThis" });
2853
- }
2854
- for (let index = 0; index < plan.typedArrayConstructors.length; index += 1) {
2855
- const observed = plan.typedArrayConstructors[index];
2856
- const declared = plan.declarations.typedArrayConstructors[index];
2857
- replacements.push({
2858
- start: observed.start,
2859
- end: observed.end,
2860
- value: `(globalThis.${ARTIFACT_GRAPH_GUARDS}.typedArrayConstructor(${JSON.stringify(guardCapability)},${JSON.stringify(declared.modulePath)},${String(declared.occurrence)},${observed.receiver}))`,
2861
- });
2862
- }
2863
- replacements.sort((left, right) => right.start - left.start);
2864
- let source = plan.source;
2865
- let previousStart = source.length;
2866
- for (const replacement of replacements) {
2867
- if (replacement.end > previousStart) {
2868
- throw artifactGraphError(
2869
- "artifact-graph-module-transform-overlap",
2870
- "Artifact graph module transforms overlap and cannot be applied deterministically.",
2871
- );
2872
- }
2873
- source = `${source.slice(0, replacement.start)}${replacement.value}${source.slice(replacement.end)}`;
2874
- previousStart = replacement.start;
2875
- }
2876
- return source;
2877
- }
2878
-
2879
- function artifactGraphGuardCapability() {
2880
- return "ordinary";
2881
- }
2882
-
2883
- async function createArtifactGraphObjectUrls(admitted, metadata, inspection) {
2884
- if (
2885
- typeof PLATFORM_CREATE_OBJECT_URL !== "function"
2886
- || typeof PLATFORM_REVOKE_OBJECT_URL !== "function"
2887
- ) {
2888
- throw artifactGraphError(
2889
- "artifact-graph-object-url-platform-unavailable",
2890
- "Artifact graph materialization requires native Blob URL creation and revocation.",
2891
- );
2892
- }
2893
- const admittedByPath = new Map(admitted.files.map((entry) => [entry.descriptor.path, entry]));
2894
- const materializedByPath = new Map();
2895
- const created = [];
2896
- const createdIdentities = new Set();
2897
- const guardCapability = artifactGraphGuardCapability();
2898
- const runtimeInspection = assertArtifactGraphRuntimeInspection(inspection);
2899
- async function materialize(descriptor, body) {
2900
- const blob = body instanceof Blob && body.type === descriptor.mediaType
2901
- ? body
2902
- : new Blob([body], { type: descriptor.mediaType });
2903
- const moduleUrl = PLATFORM_CREATE_OBJECT_URL(blob);
2904
- if (typeof moduleUrl !== "string" || !moduleUrl.startsWith("blob:")) {
2905
- throw artifactGraphError(
2906
- "artifact-graph-object-url-scheme-not-blob",
2907
- `Materialized artifact graph file ${descriptor.path} did not produce a Blob URL.`,
2908
- );
2909
- }
2910
- if (createdIdentities.has(moduleUrl)) {
2911
- throw artifactGraphError(
2912
- "artifact-graph-object-url-identity-ambiguous",
2913
- `Materialized artifact graph file ${descriptor.path} reused another file's Blob URL.`,
2914
- );
2915
- }
2916
- createdIdentities.add(moduleUrl);
2917
- created.push(moduleUrl);
2918
- materializedByPath.set(descriptor.path, completeValue({
2919
- kind: descriptor.kind,
2920
- path: descriptor.path,
2921
- sourceUrl: descriptor.sourceUrl,
2922
- revision: descriptor.revision,
2923
- moduleUrl,
2924
- mediaType: descriptor.mediaType,
2925
- ...(descriptor.sourceMediaType === descriptor.mediaType
2926
- ? {}
2927
- : { sourceMediaType: descriptor.sourceMediaType }),
2928
- runtimeRequestUrls: descriptor.runtimeRequestUrls,
2929
- ...(descriptor.redirectFinalOrigins.length < 1
2930
- ? {}
2931
- : { redirectFinalOrigins: descriptor.redirectFinalOrigins }),
2932
- }));
2933
- }
2934
- try {
2935
- for (const descriptor of metadata.files) {
2936
- if (ARTIFACT_GRAPH_JAVASCRIPT_KINDS.has(descriptor.kind)) continue;
2937
- const admittedFile = admittedByPath.get(descriptor.path)?.file;
2938
- if (!admittedFile) {
2939
- throw artifactGraphError(
2940
- "artifact-graph-materialized-source-file-missing",
2941
- `Artifact graph file ${descriptor.path} is unavailable for materialization.`,
2942
- );
2943
- }
2944
- await materialize(descriptor, admittedFile);
2945
- }
2946
- for (const path of runtimeInspection.order) {
2947
- const descriptor = metadata.filesByPath.get(path);
2948
- const plan = runtimeInspection.plans.get(path);
2949
- if (!descriptor || !plan) {
2950
- throw artifactGraphError(
2951
- "artifact-graph-runtime-inspection-incomplete",
2952
- `Artifact graph runtime inspection is incomplete for ${path}.`,
2953
- );
2954
- }
2955
- await materialize(
2956
- descriptor,
2957
- applyArtifactGraphModuleTransforms(plan, materializedByPath, guardCapability),
2958
- );
2959
- }
2960
- const files = metadata.files.map((descriptor) => {
2961
- const materialized = materializedByPath.get(descriptor.path);
2962
- if (!materialized) {
2963
- throw artifactGraphError(
2964
- "artifact-graph-materialization-incomplete",
2965
- `Artifact graph file ${descriptor.path} was not materialized.`,
2966
- );
2967
- }
2968
- return materialized;
2969
- });
2970
- return completeValue({
2971
- guardCapability,
2972
- files: completeValue(files),
2973
- release() {
2974
- for (const url of created.splice(0).reverse()) {
2975
- try {
2976
- PLATFORM_REVOKE_OBJECT_URL(url);
2977
- } catch {
2978
- // Object URL revocation follows worker termination and is best effort.
2979
- }
2980
- }
2981
- },
2982
- });
2983
- } catch (error) {
2984
- for (const url of created.splice(0).reverse()) {
2985
- try {
2986
- PLATFORM_REVOKE_OBJECT_URL(url);
2987
- } catch {
2988
- // Preserve the graph inspection or materialization error.
2989
- }
2990
- }
2991
- throw error;
2992
- }
2993
- }
2994
-
2995
1341
  function ordinaryArtifactUrl(value, base) {
2996
1342
  try {
2997
1343
  return new URL(value, base).href;
@@ -3382,9 +1728,6 @@ async function createOrdinaryArtifactObjectUrls(
3382
1728
  ? {}
3383
1729
  : { sourceMediaType: descriptor.sourceMediaType }),
3384
1730
  runtimeRequestUrls: descriptor.runtimeRequestUrls,
3385
- ...(descriptor.redirectFinalOrigins.length < 1
3386
- ? {}
3387
- : { redirectFinalOrigins: descriptor.redirectFinalOrigins }),
3388
1731
  }));
3389
1732
  }
3390
1733
  try {
@@ -3591,18 +1934,15 @@ export function createDbopfsSpeechArtifactStore({
3591
1934
  const metadata = artifactMetadata(authority);
3592
1935
  const names = storageNames(authority, metadata.files);
3593
1936
  const priorSelection = await readJsonFile(names.selection);
3594
- const legacySelection = await readJsonFile(names.legacyManifest);
3595
- const priorCount = Math.max(
3596
- Array.isArray(priorSelection?.files) ? priorSelection.files.length : 0,
3597
- Array.isArray(legacySelection?.files) ? legacySelection.files.length : 0,
3598
- );
1937
+ const priorCount = Array.isArray(priorSelection?.files)
1938
+ ? priorSelection.files.length
1939
+ : 0;
3599
1940
  const fileNames = Array.from(
3600
1941
  { length: Math.max(names.files.length, priorCount) },
3601
1942
  (_, index) => `${names.key}.${String(index).padStart(4, "0")}.artifact`,
3602
1943
  );
3603
1944
  const results = await Promise.all([
3604
1945
  removeEntry(names.selection),
3605
- removeEntry(names.legacyManifest),
3606
1946
  ...fileNames.map(removeEntry),
3607
1947
  ]);
3608
1948
  return results.some(Boolean);