@jami-studio/core 0.92.32 → 0.92.33

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.
@@ -1,5 +1,11 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.92.33
4
+
5
+ ### Patch Changes
6
+
7
+ - b400c4a: Fix a unified-worker regression in 0.92.32's workspace env baking: per-app keys (app id, base path, audience, public/protected route lists) were baked into the SHARED `process.env` of the single Cloudflare isolate, so the first app's scope-init poisoned every sibling — all apps stripped request paths against dispatch's base path and 401'd their framework routes (A2A, auth/session). Per-app keys now travel through the per-module-graph scope (`setModuleGraphEnvDefaults` in `_scope-init.js`, read via `getModuleGraphEnvDefault` fallbacks in the audience/route-access env readers), the same isolation mechanism as the 0.92.28 registry scoping. Only workspace-identical keys (`AGENT_NATIVE_WORKSPACE`, the workspace-apps manifest JSON) remain `process.env` defaults.
8
+
3
9
  ## 0.92.32
4
10
 
5
11
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.92.32",
3
+ "version": "0.92.33",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/studio-jami/jami-studio#readme",
6
6
  "bugs": {
@@ -624,53 +624,72 @@ export interface GenerateWorkerEntryOptions {
624
624
  * lean `global-scope` subpath so nothing registry-touching evaluates before
625
625
  * the scope id is set (ESM evaluates imports depth-first in order).
626
626
  *
627
- * `envDefaults` bakes the per-app workspace env (workspace-apps manifest,
628
- * app id, base path, audience, route-access lists) into the module as
629
- * `process.env` DEFAULTS. Cloudflare workerd has no filesystem and no
630
- * ambient build env, so without this the runtime falls back as if the app
631
- * were standalone `loadWorkspaceAppsManifest()` returns null and agent
632
- * discovery targets the builtin hosted prod URLs instead of the sibling
633
- * apps mounted on this origin (ask_app/call-agent "internal error"). The
634
- * Netlify preset already bakes the same keys in its generated function
635
- * entry (`setBasePathEnv`); this is the Cloudflare-preset equivalent.
636
- * Defaults never override real runtime env: the worker's per-request
637
- * bindings copy assigns binding keys on top, and baked keys only apply
638
- * when the key is absent.
627
+ * Two kinds of baked env, split deliberately (issue-49 regression lesson):
628
+ *
629
+ * - `envDefaults` workspace-IDENTICAL keys (the workspace-apps manifest,
630
+ * the workspace flag). These are safe as `process.env` DEFAULTS even
631
+ * though the unified worker shares one `process.env` across all apps,
632
+ * because every app bakes the same value. Runtime bindings still win
633
+ * (defaults only fill absent keys; the per-request bindings copy assigns
634
+ * binding keys on top).
635
+ *
636
+ * - `moduleGraphEnvDefaults` PER-APP keys (app id, base path, audience,
637
+ * public/protected route lists). These must NEVER touch the shared
638
+ * `process.env`: the first app's scope-init would win and poison every
639
+ * sibling (observed live: all apps stripped paths against dispatch's
640
+ * base path and 401'd framework routes). They are stored per module
641
+ * graph via `setModuleGraphEnvDefaults`, and env readers fall back to
642
+ * `getModuleGraphEnvDefault`.
643
+ *
644
+ * workerd has no filesystem and no ambient build env, so without this the
645
+ * runtime falls back as if the app were standalone — agent discovery
646
+ * targets builtin hosted prod URLs (ask_app "internal error") and per-app
647
+ * route access/audience declarations never apply. The Netlify preset bakes
648
+ * the same keys in its generated function entry (`setBasePathEnv`), where
649
+ * per-function isolation makes plain env safe.
639
650
  */
640
651
  export function generateScopeInitSource(
641
652
  appScopeId: string,
642
653
  envDefaults?: Record<string, string>,
654
+ moduleGraphEnvDefaults?: Record<string, string>,
643
655
  ): string {
644
- const entries = Object.entries(envDefaults ?? {}).filter(
656
+ const sharedEntries = Object.entries(envDefaults ?? {}).filter(
657
+ ([, value]) => typeof value === "string" && value !== "",
658
+ );
659
+ const perAppEntries = Object.entries(moduleGraphEnvDefaults ?? {}).filter(
645
660
  ([, value]) => typeof value === "string" && value !== "",
646
661
  );
647
- const envBlock = entries.length
662
+ const envBlock = sharedEntries.length
648
663
  ? `
649
- // Baked per-app workspace env defaults (runtime bindings still win).
664
+ // Baked workspace-identical env defaults (runtime bindings still win).
650
665
  {
651
666
  const processRef = (globalThis.process ??= { env: {} });
652
667
  processRef.env ??= {};
653
- const defaults = ${JSON.stringify(Object.fromEntries(entries))};
668
+ const defaults = ${JSON.stringify(Object.fromEntries(sharedEntries))};
654
669
  for (const key of Object.keys(defaults)) {
655
670
  if (processRef.env[key] === undefined) processRef.env[key] = defaults[key];
656
671
  }
657
672
  }
673
+ `
674
+ : "";
675
+ const moduleGraphBlock = perAppEntries.length
676
+ ? `setModuleGraphEnvDefaults(${JSON.stringify(Object.fromEntries(perAppEntries))});
658
677
  `
659
678
  : "";
660
679
  return `// AUTO-GENERATED by @agent-native/core deploy build
661
680
  // Scope globalThis-pinned framework registries to this app's module graph.
662
681
  // Evaluated FIRST in the worker entry's import graph so the scope is set
663
682
  // before any registry module initializes. See core shared/global-scope.
664
- import { setGlobalScopeId } from "@agent-native/core/global-scope";
683
+ import { setGlobalScopeId${perAppEntries.length ? ", setModuleGraphEnvDefaults" : ""} } from "@agent-native/core/global-scope";
665
684
  setGlobalScopeId(${JSON.stringify(appScopeId)});
666
- ${envBlock}`;
685
+ ${moduleGraphBlock}${envBlock}`;
667
686
  }
668
687
 
669
688
  /**
670
- * Snapshot the per-app workspace env keys that must survive into the edge
671
- * runtime. Called at build time (workspace-deploy sets these in the child
672
- * build env); the result is baked into `_scope-init.js` as process.env
673
- * defaults for runtimes with no filesystem/ambient env (workerd).
689
+ * Snapshot the workspace-IDENTICAL env keys that must survive into the edge
690
+ * runtime as shared `process.env` defaults. Per-app keys deliberately live
691
+ * in `workspaceAppModuleGraphEnvDefaultsFromBuildEnv` instead — see
692
+ * `generateScopeInitSource`.
674
693
  */
675
694
  export function workspaceEnvDefaultsFromBuildEnv(
676
695
  env: NodeJS.ProcessEnv = process.env,
@@ -678,19 +697,37 @@ export function workspaceEnvDefaultsFromBuildEnv(
678
697
  if (env.AGENT_NATIVE_WORKSPACE !== "1") return {};
679
698
  const keys = [
680
699
  "AGENT_NATIVE_WORKSPACE",
700
+ "AGENT_NATIVE_WORKSPACE_APPS_JSON",
701
+ "VITE_AGENT_NATIVE_WORKSPACE",
702
+ "VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON",
703
+ ];
704
+ const defaults: Record<string, string> = {};
705
+ for (const key of keys) {
706
+ const value = env[key];
707
+ if (typeof value === "string" && value !== "") defaults[key] = value;
708
+ }
709
+ return defaults;
710
+ }
711
+
712
+ /**
713
+ * Snapshot the PER-APP workspace env keys for this app's module graph.
714
+ * Delivered via `setModuleGraphEnvDefaults` (never shared `process.env`).
715
+ */
716
+ export function workspaceAppModuleGraphEnvDefaultsFromBuildEnv(
717
+ env: NodeJS.ProcessEnv = process.env,
718
+ ): Record<string, string> {
719
+ if (env.AGENT_NATIVE_WORKSPACE !== "1") return {};
720
+ const keys = [
681
721
  "AGENT_NATIVE_WORKSPACE_APP_ID",
682
722
  "APP_BASE_PATH",
683
723
  "AGENT_NATIVE_WORKSPACE_APP_AUDIENCE",
684
724
  "AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS",
685
725
  "AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS",
686
- "AGENT_NATIVE_WORKSPACE_APPS_JSON",
687
- "VITE_AGENT_NATIVE_WORKSPACE",
688
726
  "VITE_AGENT_NATIVE_WORKSPACE_APP_ID",
689
727
  "VITE_APP_BASE_PATH",
690
728
  "VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE",
691
729
  "VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS",
692
730
  "VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS",
693
- "VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON",
694
731
  ];
695
732
  const defaults: Record<string, string> = {};
696
733
  for (const key of keys) {
@@ -1884,7 +1921,11 @@ async function buildCloudflarePages() {
1884
1921
  if (appScopeId) {
1885
1922
  fs.writeFileSync(
1886
1923
  path.join(tmpDir, "_scope-init.js"),
1887
- generateScopeInitSource(appScopeId, workspaceEnvDefaultsFromBuildEnv()),
1924
+ generateScopeInitSource(
1925
+ appScopeId,
1926
+ workspaceEnvDefaultsFromBuildEnv(),
1927
+ workspaceAppModuleGraphEnvDefaultsFromBuildEnv(),
1928
+ ),
1888
1929
  );
1889
1930
  }
1890
1931
 
@@ -73,3 +73,35 @@ export function __deleteScopedGlobal(base: string): void {
73
73
  const key = Symbol.for(scopedGlobalKeyName(base));
74
74
  delete (globalThis as unknown as Record<symbol, unknown>)[key];
75
75
  }
76
+
77
+ /**
78
+ * Per-module-graph env defaults for unified workspace deployments.
79
+ *
80
+ * workerd has no filesystem and no ambient build env, so per-app workspace
81
+ * config (app id, base path, audience, public/protected route lists) must be
82
+ * baked into the artifact. It CANNOT go through `process.env`: the unified
83
+ * worker shares ONE `process.env` across every app's module graph, so the
84
+ * first app's baked values would poison every sibling (the exact issue-35
85
+ * class the scope id above exists for — observed live as every app stripping
86
+ * paths against dispatch's base path, 401ing all framework routes).
87
+ *
88
+ * Instead the generated scope-init module stores this graph's per-app values
89
+ * here (module scope = per app bundle), and env readers fall back to
90
+ * `getModuleGraphEnvDefault` when the ambient env lacks the key. Real runtime
91
+ * env still wins; dev/single-app graphs never set defaults, so behavior is
92
+ * unchanged there.
93
+ */
94
+ let moduleGraphEnvDefaults: Record<string, string> | null = null;
95
+
96
+ /** Set (or clear with `null`) this module graph's baked env defaults. */
97
+ export function setModuleGraphEnvDefaults(
98
+ defaults: Record<string, string> | null,
99
+ ): void {
100
+ moduleGraphEnvDefaults =
101
+ defaults && Object.keys(defaults).length > 0 ? { ...defaults } : null;
102
+ }
103
+
104
+ /** This module graph's baked default for `key`, or undefined. */
105
+ export function getModuleGraphEnvDefault(key: string): string | undefined {
106
+ return moduleGraphEnvDefaults?.[key];
107
+ }
@@ -1,3 +1,5 @@
1
+ import { getModuleGraphEnvDefault } from "./global-scope.js";
2
+
1
3
  export const WORKSPACE_APP_AUDIENCES = ["internal", "public"] as const;
2
4
 
3
5
  export type WorkspaceAppAudience = (typeof WORKSPACE_APP_AUDIENCES)[number];
@@ -48,7 +50,12 @@ export function workspaceAppAudienceFromEnv(
48
50
  const source = env ?? (typeof process !== "undefined" ? process.env : {});
49
51
  const raw =
50
52
  source.AGENT_NATIVE_WORKSPACE_APP_AUDIENCE ??
51
- source.VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE;
53
+ source.VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE ??
54
+ // Unified workerd deployments deliver per-app config via the module
55
+ // graph (shared process.env would cross-poison sibling apps).
56
+ (env === undefined
57
+ ? getModuleGraphEnvDefault("AGENT_NATIVE_WORKSPACE_APP_AUDIENCE")
58
+ : undefined);
52
59
  if (raw === undefined) return undefined;
53
60
  return normalizeWorkspaceAppAudience(raw);
54
61
  }
@@ -57,14 +64,18 @@ export function workspaceAppRouteAccessFromEnv(
57
64
  env?: Record<string, string | undefined>,
58
65
  ): WorkspaceAppRouteAccess {
59
66
  const source = env ?? (typeof process !== "undefined" ? process.env : {});
67
+ const moduleGraphFallback = (key: string) =>
68
+ env === undefined ? getModuleGraphEnvDefault(key) : undefined;
60
69
  return {
61
70
  publicPaths: normalizeWorkspaceAppPathList(
62
71
  source.AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS ??
63
- source.VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS,
72
+ source.VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS ??
73
+ moduleGraphFallback("AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS"),
64
74
  ),
65
75
  protectedPaths: normalizeWorkspaceAppPathList(
66
76
  source.AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS ??
67
- source.VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS,
77
+ source.VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS ??
78
+ moduleGraphFallback("AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS"),
68
79
  ),
69
80
  };
70
81
  }
@@ -13,8 +13,8 @@
13
13
  * Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
14
14
  */
15
15
  export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- error: string;
17
16
  ok?: undefined;
17
+ error: string;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;
@@ -48,27 +48,43 @@ export interface GenerateWorkerEntryOptions {
48
48
  * lean `global-scope` subpath so nothing registry-touching evaluates before
49
49
  * the scope id is set (ESM evaluates imports depth-first in order).
50
50
  *
51
- * `envDefaults` bakes the per-app workspace env (workspace-apps manifest,
52
- * app id, base path, audience, route-access lists) into the module as
53
- * `process.env` DEFAULTS. Cloudflare workerd has no filesystem and no
54
- * ambient build env, so without this the runtime falls back as if the app
55
- * were standalone `loadWorkspaceAppsManifest()` returns null and agent
56
- * discovery targets the builtin hosted prod URLs instead of the sibling
57
- * apps mounted on this origin (ask_app/call-agent "internal error"). The
58
- * Netlify preset already bakes the same keys in its generated function
59
- * entry (`setBasePathEnv`); this is the Cloudflare-preset equivalent.
60
- * Defaults never override real runtime env: the worker's per-request
61
- * bindings copy assigns binding keys on top, and baked keys only apply
62
- * when the key is absent.
51
+ * Two kinds of baked env, split deliberately (issue-49 regression lesson):
52
+ *
53
+ * - `envDefaults` workspace-IDENTICAL keys (the workspace-apps manifest,
54
+ * the workspace flag). These are safe as `process.env` DEFAULTS even
55
+ * though the unified worker shares one `process.env` across all apps,
56
+ * because every app bakes the same value. Runtime bindings still win
57
+ * (defaults only fill absent keys; the per-request bindings copy assigns
58
+ * binding keys on top).
59
+ *
60
+ * - `moduleGraphEnvDefaults` PER-APP keys (app id, base path, audience,
61
+ * public/protected route lists). These must NEVER touch the shared
62
+ * `process.env`: the first app's scope-init would win and poison every
63
+ * sibling (observed live: all apps stripped paths against dispatch's
64
+ * base path and 401'd framework routes). They are stored per module
65
+ * graph via `setModuleGraphEnvDefaults`, and env readers fall back to
66
+ * `getModuleGraphEnvDefault`.
67
+ *
68
+ * workerd has no filesystem and no ambient build env, so without this the
69
+ * runtime falls back as if the app were standalone — agent discovery
70
+ * targets builtin hosted prod URLs (ask_app "internal error") and per-app
71
+ * route access/audience declarations never apply. The Netlify preset bakes
72
+ * the same keys in its generated function entry (`setBasePathEnv`), where
73
+ * per-function isolation makes plain env safe.
63
74
  */
64
- export declare function generateScopeInitSource(appScopeId: string, envDefaults?: Record<string, string>): string;
75
+ export declare function generateScopeInitSource(appScopeId: string, envDefaults?: Record<string, string>, moduleGraphEnvDefaults?: Record<string, string>): string;
65
76
  /**
66
- * Snapshot the per-app workspace env keys that must survive into the edge
67
- * runtime. Called at build time (workspace-deploy sets these in the child
68
- * build env); the result is baked into `_scope-init.js` as process.env
69
- * defaults for runtimes with no filesystem/ambient env (workerd).
77
+ * Snapshot the workspace-IDENTICAL env keys that must survive into the edge
78
+ * runtime as shared `process.env` defaults. Per-app keys deliberately live
79
+ * in `workspaceAppModuleGraphEnvDefaultsFromBuildEnv` instead — see
80
+ * `generateScopeInitSource`.
70
81
  */
71
82
  export declare function workspaceEnvDefaultsFromBuildEnv(env?: NodeJS.ProcessEnv): Record<string, string>;
83
+ /**
84
+ * Snapshot the PER-APP workspace env keys for this app's module graph.
85
+ * Delivered via `setModuleGraphEnvDefaults` (never shared `process.env`).
86
+ */
87
+ export declare function workspaceAppModuleGraphEnvDefaultsFromBuildEnv(env?: NodeJS.ProcessEnv): Record<string, string>;
72
88
  /**
73
89
  * Derive the workspace app id from a mounted app base path ("/assets" →
74
90
  * "assets"). Returns null for unmounted (root) builds.
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":"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"}
@@ -523,66 +523,99 @@ export const CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES = {
523
523
  * lean `global-scope` subpath so nothing registry-touching evaluates before
524
524
  * the scope id is set (ESM evaluates imports depth-first in order).
525
525
  *
526
- * `envDefaults` bakes the per-app workspace env (workspace-apps manifest,
527
- * app id, base path, audience, route-access lists) into the module as
528
- * `process.env` DEFAULTS. Cloudflare workerd has no filesystem and no
529
- * ambient build env, so without this the runtime falls back as if the app
530
- * were standalone `loadWorkspaceAppsManifest()` returns null and agent
531
- * discovery targets the builtin hosted prod URLs instead of the sibling
532
- * apps mounted on this origin (ask_app/call-agent "internal error"). The
533
- * Netlify preset already bakes the same keys in its generated function
534
- * entry (`setBasePathEnv`); this is the Cloudflare-preset equivalent.
535
- * Defaults never override real runtime env: the worker's per-request
536
- * bindings copy assigns binding keys on top, and baked keys only apply
537
- * when the key is absent.
526
+ * Two kinds of baked env, split deliberately (issue-49 regression lesson):
527
+ *
528
+ * - `envDefaults` workspace-IDENTICAL keys (the workspace-apps manifest,
529
+ * the workspace flag). These are safe as `process.env` DEFAULTS even
530
+ * though the unified worker shares one `process.env` across all apps,
531
+ * because every app bakes the same value. Runtime bindings still win
532
+ * (defaults only fill absent keys; the per-request bindings copy assigns
533
+ * binding keys on top).
534
+ *
535
+ * - `moduleGraphEnvDefaults` PER-APP keys (app id, base path, audience,
536
+ * public/protected route lists). These must NEVER touch the shared
537
+ * `process.env`: the first app's scope-init would win and poison every
538
+ * sibling (observed live: all apps stripped paths against dispatch's
539
+ * base path and 401'd framework routes). They are stored per module
540
+ * graph via `setModuleGraphEnvDefaults`, and env readers fall back to
541
+ * `getModuleGraphEnvDefault`.
542
+ *
543
+ * workerd has no filesystem and no ambient build env, so without this the
544
+ * runtime falls back as if the app were standalone — agent discovery
545
+ * targets builtin hosted prod URLs (ask_app "internal error") and per-app
546
+ * route access/audience declarations never apply. The Netlify preset bakes
547
+ * the same keys in its generated function entry (`setBasePathEnv`), where
548
+ * per-function isolation makes plain env safe.
538
549
  */
539
- export function generateScopeInitSource(appScopeId, envDefaults) {
540
- const entries = Object.entries(envDefaults ?? {}).filter(([, value]) => typeof value === "string" && value !== "");
541
- const envBlock = entries.length
550
+ export function generateScopeInitSource(appScopeId, envDefaults, moduleGraphEnvDefaults) {
551
+ const sharedEntries = Object.entries(envDefaults ?? {}).filter(([, value]) => typeof value === "string" && value !== "");
552
+ const perAppEntries = Object.entries(moduleGraphEnvDefaults ?? {}).filter(([, value]) => typeof value === "string" && value !== "");
553
+ const envBlock = sharedEntries.length
542
554
  ? `
543
- // Baked per-app workspace env defaults (runtime bindings still win).
555
+ // Baked workspace-identical env defaults (runtime bindings still win).
544
556
  {
545
557
  const processRef = (globalThis.process ??= { env: {} });
546
558
  processRef.env ??= {};
547
- const defaults = ${JSON.stringify(Object.fromEntries(entries))};
559
+ const defaults = ${JSON.stringify(Object.fromEntries(sharedEntries))};
548
560
  for (const key of Object.keys(defaults)) {
549
561
  if (processRef.env[key] === undefined) processRef.env[key] = defaults[key];
550
562
  }
551
563
  }
564
+ `
565
+ : "";
566
+ const moduleGraphBlock = perAppEntries.length
567
+ ? `setModuleGraphEnvDefaults(${JSON.stringify(Object.fromEntries(perAppEntries))});
552
568
  `
553
569
  : "";
554
570
  return `// AUTO-GENERATED by @agent-native/core deploy build
555
571
  // Scope globalThis-pinned framework registries to this app's module graph.
556
572
  // Evaluated FIRST in the worker entry's import graph so the scope is set
557
573
  // before any registry module initializes. See core shared/global-scope.
558
- import { setGlobalScopeId } from "@agent-native/core/global-scope";
574
+ import { setGlobalScopeId${perAppEntries.length ? ", setModuleGraphEnvDefaults" : ""} } from "@agent-native/core/global-scope";
559
575
  setGlobalScopeId(${JSON.stringify(appScopeId)});
560
- ${envBlock}`;
576
+ ${moduleGraphBlock}${envBlock}`;
561
577
  }
562
578
  /**
563
- * Snapshot the per-app workspace env keys that must survive into the edge
564
- * runtime. Called at build time (workspace-deploy sets these in the child
565
- * build env); the result is baked into `_scope-init.js` as process.env
566
- * defaults for runtimes with no filesystem/ambient env (workerd).
579
+ * Snapshot the workspace-IDENTICAL env keys that must survive into the edge
580
+ * runtime as shared `process.env` defaults. Per-app keys deliberately live
581
+ * in `workspaceAppModuleGraphEnvDefaultsFromBuildEnv` instead — see
582
+ * `generateScopeInitSource`.
567
583
  */
568
584
  export function workspaceEnvDefaultsFromBuildEnv(env = process.env) {
569
585
  if (env.AGENT_NATIVE_WORKSPACE !== "1")
570
586
  return {};
571
587
  const keys = [
572
588
  "AGENT_NATIVE_WORKSPACE",
589
+ "AGENT_NATIVE_WORKSPACE_APPS_JSON",
590
+ "VITE_AGENT_NATIVE_WORKSPACE",
591
+ "VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON",
592
+ ];
593
+ const defaults = {};
594
+ for (const key of keys) {
595
+ const value = env[key];
596
+ if (typeof value === "string" && value !== "")
597
+ defaults[key] = value;
598
+ }
599
+ return defaults;
600
+ }
601
+ /**
602
+ * Snapshot the PER-APP workspace env keys for this app's module graph.
603
+ * Delivered via `setModuleGraphEnvDefaults` (never shared `process.env`).
604
+ */
605
+ export function workspaceAppModuleGraphEnvDefaultsFromBuildEnv(env = process.env) {
606
+ if (env.AGENT_NATIVE_WORKSPACE !== "1")
607
+ return {};
608
+ const keys = [
573
609
  "AGENT_NATIVE_WORKSPACE_APP_ID",
574
610
  "APP_BASE_PATH",
575
611
  "AGENT_NATIVE_WORKSPACE_APP_AUDIENCE",
576
612
  "AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS",
577
613
  "AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS",
578
- "AGENT_NATIVE_WORKSPACE_APPS_JSON",
579
- "VITE_AGENT_NATIVE_WORKSPACE",
580
614
  "VITE_AGENT_NATIVE_WORKSPACE_APP_ID",
581
615
  "VITE_APP_BASE_PATH",
582
616
  "VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE",
583
617
  "VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS",
584
618
  "VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS",
585
- "VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON",
586
619
  ];
587
620
  const defaults = {};
588
621
  for (const key of keys) {
@@ -1566,7 +1599,7 @@ async function buildCloudflarePages() {
1566
1599
  const tmpEntry = path.join(tmpDir, "index.js");
1567
1600
  fs.writeFileSync(tmpEntry, adjustedEntry);
1568
1601
  if (appScopeId) {
1569
- fs.writeFileSync(path.join(tmpDir, "_scope-init.js"), generateScopeInitSource(appScopeId, workspaceEnvDefaultsFromBuildEnv()));
1602
+ fs.writeFileSync(path.join(tmpDir, "_scope-init.js"), generateScopeInitSource(appScopeId, workspaceEnvDefaultsFromBuildEnv(), workspaceAppModuleGraphEnvDefaultsFromBuildEnv()));
1570
1603
  }
1571
1604
  if (includeReactRouterSsr) {
1572
1605
  copyDir(serverDir, path.join(tmpDir, "server"));