@elizaos/app-core 2.0.0-alpha.59 → 2.0.0-alpha.61

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.
@@ -0,0 +1,2 @@
1
+ $ bunx @biomejs/biome check ./src/App.tsx ./src/actions ./src/api ./src/autonomy ./src/bridge ./src/chat ./src/coding ./src/components ./src/config ./src/events ./src/hooks ./src/i18n ./src/index.ts ./src/navigation ./src/platform ./src/providers ./src/state ./src/types ./src/utils ./src/voice ./src/ambient.d.ts
2
+ Checked 253 files in 344ms. No fixes applied.
@@ -0,0 +1,2 @@
1
+
2
+ $ test -f ../ui/dist/index.d.ts || (cd ../ui && bun run build) && tsc --noEmit -p tsconfig.json
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionStep.d.ts","sourceRoot":"","sources":["../../../src/components/onboarding/ConnectionStep.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,cAAc,4CAq+C7B"}
1
+ {"version":3,"file":"ConnectionStep.d.ts","sourceRoot":"","sources":["../../../src/components/onboarding/ConnectionStep.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,cAAc,4CAo+C7B"}
@@ -112,8 +112,7 @@ export function ConnectionStep() {
112
112
  };
113
113
  const providers = onboardingOptions?.providers ?? [];
114
114
  const elizaCloudReady = elizaCloudConnected ||
115
- (onboardingRunMode === "cloud" &&
116
- onboardingCloudProvider === "elizacloud" &&
115
+ (onboardingProvider === "elizacloud" &&
117
116
  onboardingApiKey.trim().length > 0);
118
117
  const showProviderSelection = onboardingRemoteConnected || onboardingRunMode === "local";
119
118
  const recommendedIds = new Set([
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/app-core",
3
- "version": "2.0.0-alpha.59",
3
+ "version": "2.0.0-alpha.60",
4
4
  "description": "Shared application core for elizaOS shells and white-label apps.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -174,8 +174,8 @@
174
174
  "@capacitor/haptics": "8.0.0",
175
175
  "@capacitor/keyboard": "8.0.0",
176
176
  "@capacitor/preferences": "^8.0.1",
177
- "@elizaos/autonomous": "^2.0.0-alpha.59",
178
- "@elizaos/ui": "^2.0.0-alpha.59",
177
+ "@elizaos/autonomous": "^2.0.0-alpha.60",
178
+ "@elizaos/ui": "^2.0.0-alpha.60",
179
179
  "@lifo-sh/core": "0.4.4",
180
180
  "@lifo-sh/ui": "0.4.2",
181
181
  "@pixiv/three-vrm": "^3.4.5",
@@ -1 +1 @@
1
- {"version":3,"file":"AppContext.d.ts","sourceRoot":"","sources":["../../src/state/AppContext.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AACf,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,oBAAoB,CAAC;AAuK5B,OAAO,EACL,KAAK,YAAY,EACjB,sBAAsB,EACtB,YAAY,EACZ,kCAAkC,EAClC,KAAK,UAAU,EACf,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,YAAY,EACZ,cAAc,EACd,KAAK,aAAa,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,0BAA0B,EAC/B,yBAAyB,EACzB,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,8BAA8B,EACnC,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,6BAA6B,EAC7B,oBAAoB,EACpB,gBAAgB,EAChB,4BAA4B,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,4BAA4B,EAC5B,qBAAqB,EACrB,6BAA6B,EAC7B,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,EAC7B,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,WAAW,EACX,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,MAAM,EACN,SAAS,GACV,MAAM,YAAY,CAAC;AAkKpB,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,QAAQ,EAAE,iBAAiB,GAC5B,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACpC,2CA02KA"}
1
+ {"version":3,"file":"AppContext.d.ts","sourceRoot":"","sources":["../../src/state/AppContext.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AACf,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,oBAAoB,CAAC;AAuK5B,OAAO,EACL,KAAK,YAAY,EACjB,sBAAsB,EACtB,YAAY,EACZ,kCAAkC,EAClC,KAAK,UAAU,EACf,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,YAAY,EACZ,cAAc,EACd,KAAK,aAAa,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,0BAA0B,EAC/B,yBAAyB,EACzB,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,8BAA8B,EACnC,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,6BAA6B,EAC7B,oBAAoB,EACpB,gBAAgB,EAChB,4BAA4B,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,4BAA4B,EAC5B,qBAAqB,EACrB,6BAA6B,EAC7B,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,EAC7B,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,WAAW,EACX,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,MAAM,EACN,SAAS,GACV,MAAM,YAAY,CAAC;AAkKpB,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,QAAQ,EAAE,iBAAiB,GAC5B,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACpC,2CA82KA"}
@@ -2924,7 +2924,11 @@ export function AppProvider({ children, branding: brandingOverrides, }) {
2924
2924
  onboardingRemoteToken,
2925
2925
  onboardingSmallModel,
2926
2926
  onboardingLargeModel,
2927
- }) ?? onboardingResumeConnectionRef.current;
2927
+ }) ?? (onboardingProvider === "elizacloud" ? {
2928
+ kind: "cloud-managed",
2929
+ cloudProvider: "elizacloud",
2930
+ apiKey: onboardingApiKey.trim() || undefined,
2931
+ } : onboardingResumeConnectionRef.current);
2928
2932
  if (!connection) {
2929
2933
  throw new Error("Onboarding connection is incomplete");
2930
2934
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/app-core",
3
- "version": "2.0.0-alpha.59",
3
+ "version": "2.0.0-alpha.61",
4
4
  "description": "Shared application core for elizaOS shells and white-label apps.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -69,8 +69,8 @@
69
69
  "@capacitor/haptics": "8.0.0",
70
70
  "@capacitor/keyboard": "8.0.0",
71
71
  "@capacitor/preferences": "^8.0.1",
72
- "@elizaos/autonomous": "2.0.0-alpha.59",
73
- "@elizaos/ui": "2.0.0-alpha.59",
72
+ "@elizaos/autonomous": "2.0.0-alpha.61",
73
+ "@elizaos/ui": "2.0.0-alpha.61",
74
74
  "@lifo-sh/core": "0.4.4",
75
75
  "@lifo-sh/ui": "0.4.2",
76
76
  "@pixiv/three-vrm": "^3.4.5",
@@ -90,5 +90,5 @@
90
90
  "tailwindcss": "^4.1.18",
91
91
  "typescript": "^5.9.3"
92
92
  },
93
- "gitHead": "481d7c4e410b11531ba7f1cdaee8f5b2b142f7ad"
93
+ "gitHead": "6a8cda9c74e9d56d340a652da9940e1b3c7bd472"
94
94
  }
@@ -5,12 +5,15 @@ interface AvatarLoaderProps {
5
5
  fullScreen?: boolean;
6
6
  /** When true, fades the loader out (use before unmounting) */
7
7
  fadingOut?: boolean;
8
+ /** Optional progress value from 0 to 100. If provided, overrides the infinite loading animation. */
9
+ progress?: number;
8
10
  }
9
11
 
10
12
  export function AvatarLoader({
11
13
  label = "Initializing entity",
12
14
  fullScreen = false,
13
15
  fadingOut = false,
16
+ progress,
14
17
  }: AvatarLoaderProps) {
15
18
  return (
16
19
  <div
@@ -63,11 +66,12 @@ export function AvatarLoader({
63
66
  >
64
67
  <div
65
68
  style={{
66
- width: "60%",
69
+ width: typeof progress === "number" ? `${Math.max(0, Math.min(100, progress))}%` : "60%",
67
70
  height: "100%",
68
71
  background: "var(--text-strong)",
69
72
  boxShadow: "0 0 8px rgba(255, 255, 255, 0.3)",
70
- animation: "avatar-loader-progress 2s ease-in-out infinite",
73
+ transition: typeof progress === "number" ? "width 0.3s ease-out" : "none",
74
+ animation: typeof progress === "number" ? "none" : "avatar-loader-progress 2s ease-in-out infinite",
71
75
  }}
72
76
  />
73
77
  </div>
@@ -8,7 +8,8 @@ import {
8
8
  useApp,
9
9
  } from "@elizaos/app-core/state";
10
10
  import { resolveAppAssetUrl } from "@elizaos/app-core/utils";
11
- import { useEffect } from "react";
11
+ import { useEffect, useState } from "react";
12
+ import { useBranding } from "../../config/branding";
12
13
  import { VrmStage } from "./companion/VrmStage";
13
14
  import { ActivateStep } from "./onboarding/ActivateStep";
14
15
  import { ConnectionStep } from "./onboarding/ConnectionStep";
@@ -23,6 +24,11 @@ const DISABLE_ONBOARDING_VRM =
23
24
  String(import.meta.env.VITE_E2E_DISABLE_VRM ?? "") === "1";
24
25
 
25
26
  export function OnboardingWizard() {
27
+ const branding = useBranding();
28
+ const isEliza = branding.appName === "Eliza";
29
+ const disableVrm = DISABLE_ONBOARDING_VRM || isEliza;
30
+ const [revealStarted, setRevealStarted] = useState(disableVrm);
31
+
26
32
  const {
27
33
  onboardingStep,
28
34
  selectedVrmIndex,
@@ -82,7 +88,7 @@ export function OnboardingWizard() {
82
88
  {!isCharacterSelect && <div className="onboarding-bg-overlay" />}
83
89
 
84
90
  {/* Keep browser E2E runs lightweight and deterministic by skipping VRM boot. */}
85
- {DISABLE_ONBOARDING_VRM ? (
91
+ {disableVrm ? (
86
92
  <div
87
93
  aria-hidden="true"
88
94
  className="absolute inset-0 z-10 pointer-events-none"
@@ -98,12 +104,23 @@ export function OnboardingWizard() {
98
104
  fallbackPreviewUrl={fallbackPreview}
99
105
  cameraProfile="companion_close"
100
106
  initialCompanionZoomNormalized={1}
107
+ onRevealStart={() => setRevealStarted(true)}
101
108
  t={t}
102
109
  />
103
110
  )}
104
111
 
105
- {/* Corner decorations */}
106
- <svg
112
+ <div
113
+ style={{
114
+ position: "absolute",
115
+ inset: 0,
116
+ pointerEvents: revealStarted ? "auto" : "none",
117
+ opacity: revealStarted ? 1 : 0,
118
+ transition: "opacity 1.2s ease-in-out",
119
+ zIndex: 40,
120
+ }}
121
+ >
122
+ {/* Corner decorations */}
123
+ <svg
107
124
  className="onboarding-corner onboarding-corner--tl"
108
125
  viewBox="0 0 36 36"
109
126
  fill="none"
@@ -216,6 +233,7 @@ export function OnboardingWizard() {
216
233
  </OnboardingPanel>
217
234
  </div>
218
235
  )}
236
+ </div>
219
237
  </div>
220
238
  );
221
239
  }
@@ -63,6 +63,7 @@ const VrmStageLayer = memo(function VrmStageLayer({
63
63
  }) {
64
64
  const [vrmLoaded, setVrmLoaded] = useState(false);
65
65
  const [showVrmFallback, setShowVrmFallback] = useState(false);
66
+ const [loadingProgress, setLoadingProgress] = useState<number | undefined>(undefined);
66
67
  const chatAvatarVoice = useChatAvatarVoiceState();
67
68
 
68
69
  const handleVrmEngineReady = useCallback(
@@ -91,6 +92,9 @@ const VrmStageLayer = memo(function VrmStageLayer({
91
92
  );
92
93
 
93
94
  const handleVrmEngineState = useCallback((state: VrmEngineState) => {
95
+ if (state.loadingProgress !== undefined) {
96
+ setLoadingProgress(Math.round(state.loadingProgress * 100));
97
+ }
94
98
  if (state.vrmLoaded) {
95
99
  setVrmLoaded(true);
96
100
  setShowVrmFallback(false);
@@ -141,7 +145,7 @@ const VrmStageLayer = memo(function VrmStageLayer({
141
145
  )}
142
146
  {visible && !vrmLoaded && !showVrmFallback && (
143
147
  <div className="absolute inset-0" style={{ zIndex }}>
144
- <AvatarLoader />
148
+ <AvatarLoader progress={loadingProgress} />
145
149
  </div>
146
150
  )}
147
151
  </>
@@ -157,6 +161,7 @@ export const VrmStage = memo(function VrmStage({
157
161
  initialCompanionZoomNormalized,
158
162
  onEngineReady,
159
163
  onLayerEngineReady,
164
+ onRevealStart,
160
165
  playWaveOnAvatarChange = false,
161
166
  preloadAvatars = [],
162
167
  t,
@@ -169,6 +174,7 @@ export const VrmStage = memo(function VrmStage({
169
174
  initialCompanionZoomNormalized?: number;
170
175
  onEngineReady?: (engine: VrmEngine) => void;
171
176
  onLayerEngineReady?: (vrmPath: string, engine: VrmEngine) => void;
177
+ onRevealStart?: () => void;
172
178
  playWaveOnAvatarChange?: boolean;
173
179
  preloadAvatars?: readonly VrmStageAvatarEntry[];
174
180
  t: TranslateFn;
@@ -244,9 +250,10 @@ export const VrmStage = memo(function VrmStage({
244
250
  const handleRevealStart = useCallback(
245
251
  (layerPath: string) => {
246
252
  if (layerPath !== currentPathRef.current) return;
253
+ onRevealStart?.();
247
254
  scheduleGreetingWave();
248
255
  },
249
- [scheduleGreetingWave],
256
+ [onRevealStart, scheduleGreetingWave],
250
257
  );
251
258
 
252
259
  useEffect(() => {
@@ -53,6 +53,7 @@ export type VrmEngineState = {
53
53
  idleTime: number;
54
54
  idleTracks: number;
55
55
  revealStarted: boolean;
56
+ loadingProgress?: number;
56
57
  };
57
58
 
58
59
  type DebugVector3 = {
@@ -455,15 +456,50 @@ async function decompressGzipBuffer(buffer: ArrayBuffer): Promise<ArrayBuffer> {
455
456
  async function loadGltfAsset(
456
457
  loader: GLTFLoader,
457
458
  url: string,
459
+ onProgress?: (progress: number) => void,
458
460
  ): Promise<Awaited<ReturnType<GLTFLoader["loadAsync"]>>> {
459
461
  const response = await fetch(url);
460
462
  if (!response.ok) {
461
463
  throw new Error(`Failed to fetch VRM asset: ${response.status}`);
462
464
  }
463
- let buffer = await response.arrayBuffer();
465
+
466
+ const contentLength = Number(response.headers.get("content-length") || 0);
467
+
468
+ let buffer: ArrayBuffer;
469
+ if (!contentLength || !response.body || !onProgress) {
470
+ buffer = await response.arrayBuffer();
471
+ onProgress?.(1);
472
+ } else {
473
+ const reader = response.body.getReader();
474
+ let received = 0;
475
+ const chunks: Uint8Array[] = [];
476
+ for (;;) {
477
+ const { done, value } = await reader.read();
478
+ if (done) break;
479
+ if (value) {
480
+ chunks.push(value);
481
+ received += value.length;
482
+ onProgress(Math.min(received / contentLength, 1));
483
+ }
484
+ }
485
+ const combined = new Uint8Array(received);
486
+ let offset = 0;
487
+ for (const chunk of chunks) {
488
+ combined.set(chunk, offset);
489
+ offset += chunk.length;
490
+ }
491
+ buffer = combined.buffer;
492
+ }
493
+
464
494
  if (!isGzipBuffer(buffer)) {
465
- return await loader.loadAsync(url);
495
+ const objectUrl = URL.createObjectURL(new Blob([buffer], { type: "model/gltf-binary" }));
496
+ try {
497
+ return await loader.loadAsync(objectUrl);
498
+ } finally {
499
+ URL.revokeObjectURL(objectUrl);
500
+ }
466
501
  }
502
+
467
503
  buffer = await decompressGzipBuffer(buffer);
468
504
  const objectUrl = URL.createObjectURL(
469
505
  new Blob([buffer], { type: "model/gltf-binary" }),
@@ -543,6 +579,7 @@ export class VrmEngine {
543
579
  private vrmReady = false;
544
580
  private lastLoadError: string | null = null;
545
581
  private teleportProgress = 1.0;
582
+ private loadingProgress = 0;
546
583
  private teleportProgressUniform: { value: number } | null = null;
547
584
  private teleportDissolvedMaterials: THREE.Material[] = [];
548
585
  private teleportFallbackShaders: TeleportFallbackShader[] = [];
@@ -1813,6 +1850,7 @@ export class VrmEngine {
1813
1850
  idleTime: this.idleAction?.time ?? 0,
1814
1851
  idleTracks: this.idleAction?.getClip()?.tracks.length ?? 0,
1815
1852
  revealStarted: this.revealStarted,
1853
+ loadingProgress: this.loadingProgress,
1816
1854
  };
1817
1855
  }
1818
1856
  setMouthOpen(value: number): void {
@@ -2050,6 +2088,8 @@ export class VrmEngine {
2050
2088
  this.emoteClipCache.clear();
2051
2089
  }
2052
2090
  this.lastLoadError = null;
2091
+ this.loadingProgress = 0;
2092
+ this.onUpdate?.();
2053
2093
  const loader = new GLTFLoader();
2054
2094
  configureVrmGltfLoader(loader);
2055
2095
  const webGpuNodes =
@@ -2067,7 +2107,12 @@ export class VrmEngine {
2067
2107
  });
2068
2108
  let gltf: Awaited<ReturnType<GLTFLoader["loadAsync"]>>;
2069
2109
  try {
2070
- gltf = await loadGltfAsset(loader, url);
2110
+ gltf = await loadGltfAsset(loader, url, (progress) => {
2111
+ if (this.vrmLoadRequestId === requestId && !this.loadingAborted) {
2112
+ this.loadingProgress = progress;
2113
+ this.onUpdate?.();
2114
+ }
2115
+ });
2071
2116
  } catch (error) {
2072
2117
  if (!this.loadingAborted && requestId === this.vrmLoadRequestId) {
2073
2118
  this.lastLoadError =
@@ -152,8 +152,7 @@ export function ConnectionStep() {
152
152
  const providers = onboardingOptions?.providers ?? [];
153
153
  const elizaCloudReady =
154
154
  elizaCloudConnected ||
155
- (onboardingRunMode === "cloud" &&
156
- onboardingCloudProvider === "elizacloud" &&
155
+ (onboardingProvider === "elizacloud" &&
157
156
  onboardingApiKey.trim().length > 0);
158
157
  const showProviderSelection =
159
158
  onboardingRemoteConnected || onboardingRunMode === "local";
@@ -1,16 +1,23 @@
1
1
  import { ONBOARDING_STEPS, useApp } from "@elizaos/app-core/state";
2
+ import { useBranding } from "../../config/branding";
2
3
 
3
4
  export function OnboardingStepNav() {
4
5
  const { onboardingStep, t } = useApp();
6
+ const branding = useBranding();
5
7
 
6
- const currentIndex = ONBOARDING_STEPS.findIndex(
8
+ const isEliza = branding.appName === "Eliza";
9
+ const activeSteps = isEliza
10
+ ? ONBOARDING_STEPS.filter((s) => s.id === "connection" || s.id === "activate")
11
+ : ONBOARDING_STEPS;
12
+
13
+ const currentIndex = activeSteps.findIndex(
7
14
  (s) => s.id === onboardingStep,
8
15
  );
9
16
 
10
17
  return (
11
18
  <div className="onboarding-left">
12
19
  <div className={`onboarding-step-list step-${currentIndex}`}>
13
- {ONBOARDING_STEPS.map((step, i) => {
20
+ {activeSteps.map((step, i) => {
14
21
  let state = "";
15
22
  if (i < currentIndex) state = "onboarding-step-item--done";
16
23
  else if (i === currentIndex) state = "onboarding-step-item--active";
@@ -4002,7 +4002,11 @@ export function AppProvider({
4002
4002
  onboardingRemoteToken,
4003
4003
  onboardingSmallModel,
4004
4004
  onboardingLargeModel,
4005
- }) ?? onboardingResumeConnectionRef.current;
4005
+ }) ?? (onboardingProvider === "elizacloud" ? {
4006
+ kind: "cloud-managed" as const,
4007
+ cloudProvider: "elizacloud",
4008
+ apiKey: onboardingApiKey.trim() || undefined,
4009
+ } : onboardingResumeConnectionRef.current);
4006
4010
  if (!connection) {
4007
4011
  throw new Error("Onboarding connection is incomplete");
4008
4012
  }