@elizaos/app-core 2.0.0-alpha.13 → 2.0.0-alpha.15
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.
- package/.turbo/turbo-build.log +0 -1
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +26 -12
- package/dist/api/client.d.ts +3 -3
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +24 -13
- package/dist/bridge/plugin-bridge.d.ts.map +1 -1
- package/dist/components/AvatarLoader.d.ts +3 -1
- package/dist/components/AvatarLoader.d.ts.map +1 -1
- package/dist/components/AvatarLoader.js +4 -1
- package/dist/components/BscTradePanel.d.ts +1 -1
- package/dist/components/BscTradePanel.d.ts.map +1 -1
- package/dist/components/CharacterView.d.ts.map +1 -1
- package/dist/components/CharacterView.js +50 -15
- package/dist/components/ChatView.js +1 -1
- package/dist/components/ConfigPageView.d.ts.map +1 -1
- package/dist/components/ConfigPageView.js +9 -8
- package/dist/components/ConversationsSidebar.js +1 -1
- package/dist/components/CustomActionEditor.js +1 -1
- package/dist/components/FineTuningView.d.ts.map +1 -1
- package/dist/components/FineTuningView.js +2 -2
- package/dist/components/GlobalEmoteOverlay.d.ts.map +1 -1
- package/dist/components/GlobalEmoteOverlay.js +1 -1
- package/dist/components/HeartbeatsView.js +1 -1
- package/dist/components/LoadingScreen.d.ts.map +1 -1
- package/dist/components/LoadingScreen.js +38 -7
- package/dist/components/OnboardingWizard.js +1 -1
- package/dist/components/PluginsView.d.ts.map +1 -1
- package/dist/components/PluginsView.js +4 -1
- package/dist/components/ShellOverlays.js +1 -1
- package/dist/components/VoiceConfigView.d.ts.map +1 -1
- package/dist/components/VoiceConfigView.js +4 -2
- package/dist/components/avatar/VrmEngine.d.ts +2 -0
- package/dist/components/avatar/VrmEngine.d.ts.map +1 -1
- package/dist/components/avatar/VrmEngine.js +14 -6
- package/dist/components/companion/CompanionSceneHost.d.ts +1 -1
- package/dist/components/companion/CompanionSceneHost.d.ts.map +1 -1
- package/dist/components/companion/CompanionSceneHost.js +1 -1
- package/dist/components/index.d.ts +10 -10
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +10 -10
- package/dist/components/inventory/TokensTable.js +2 -2
- package/dist/components/onboarding/IdentityStep.d.ts.map +1 -1
- package/dist/components/onboarding/IdentityStep.js +1 -1
- package/dist/components/shared/ShellHeaderControls.js +1 -1
- package/dist/config/config-field.d.ts.map +1 -1
- package/dist/config/config-field.js +7 -8
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/hooks/useVoiceChat.d.ts.map +1 -1
- package/dist/hooks/useVoiceChat.js +3 -1
- package/dist/i18n/locales/en.json +1192 -1192
- package/dist/i18n/locales/es.json +1192 -1192
- package/dist/i18n/locales/ko.json +1192 -1192
- package/dist/i18n/locales/pt.json +1192 -1192
- package/dist/i18n/locales/zh-CN.json +1192 -1192
- package/dist/package.json +181 -0
- package/dist/platform/lifo.d.ts.map +1 -1
- package/dist/platform/lifo.js +4 -1
- package/dist/state/AppContext.d.ts.map +1 -1
- package/dist/state/AppContext.js +23 -6
- package/dist/state/internal.d.ts +1 -1
- package/dist/state/internal.d.ts.map +1 -1
- package/dist/state/internal.js +1 -1
- package/dist/state/parsers.d.ts.map +1 -1
- package/dist/state/parsers.js +3 -2
- package/dist/state/persistence.js +1 -1
- package/dist/styles/anime.css +6324 -0
- package/dist/styles/base.css +196 -0
- package/dist/styles/onboarding-game.css +738 -0
- package/dist/styles/styles.css +2087 -0
- package/dist/styles/xterm.css +241 -0
- package/package.json +4 -4
- package/src/App.tsx +35 -14
- package/src/ambient.d.ts +5 -5
- package/src/api/client.ts +36 -23
- package/src/bridge/plugin-bridge.ts +1 -1
- package/src/components/AvatarLoader.tsx +6 -0
- package/src/components/BscTradePanel.tsx +1 -1
- package/src/components/CharacterView.tsx +536 -367
- package/src/components/ChatView.tsx +3 -3
- package/src/components/ConfigPageView.tsx +9 -8
- package/src/components/ConversationsSidebar.tsx +1 -1
- package/src/components/CustomActionEditor.tsx +6 -6
- package/src/components/FineTuningView.tsx +6 -3
- package/src/components/GlobalEmoteOverlay.tsx +1 -4
- package/src/components/HeartbeatsView.tsx +1 -1
- package/src/components/InventoryView.tsx +2 -2
- package/src/components/LoadingScreen.tsx +39 -6
- package/src/components/OnboardingWizard.tsx +1 -1
- package/src/components/PluginsView.tsx +6 -0
- package/src/components/ShellOverlays.tsx +1 -1
- package/src/components/VoiceConfigView.tsx +4 -5
- package/src/components/avatar/VrmEngine.ts +25 -7
- package/src/components/companion/CompanionSceneHost.tsx +5 -1
- package/src/components/index.ts +10 -10
- package/src/components/inventory/TokensTable.tsx +2 -2
- package/src/components/onboarding/IdentityStep.tsx +9 -13
- package/src/components/shared/ShellHeaderControls.tsx +1 -1
- package/src/config/config-field.tsx +7 -8
- package/src/config/index.ts +3 -3
- package/src/hooks/useVoiceChat.ts +5 -3
- package/src/platform/lifo.ts +14 -4
- package/src/state/AppContext.tsx +24 -1
- package/src/state/internal.ts +6 -6
- package/src/state/parsers.ts +4 -3
- package/src/state/persistence.ts +1 -1
- package/test/app/MessageContent.test.tsx +42 -0
- package/test/app/bug-report-modal.test.tsx +3 -3
- package/test/app/chat-view.test.tsx +3 -3
- package/test/app/cloud-login-lock.test.ts +3 -2
- package/test/app/custom-actions-smoke.test.ts +3 -3
- package/test/app/onboarding-language.test.tsx +3 -3
- package/test/app/pages-navigation-smoke.e2e.test.ts +13 -8
- package/test/app/plugin-bridge.test.ts +1 -1
- package/test/app/provider-dropdown-default.test.tsx +2 -4
- package/test/app/restart-banner.test.tsx +3 -3
- package/test/app/shell-mode-switching.e2e.test.ts +6 -6
- package/test/app/shell-mode-tab-memory.test.tsx +1 -1
- package/test/app/startup-chat.e2e.test.ts +3 -3
- package/test/app/triggers-view.e2e.test.ts +3 -2
- package/test/app/wallet-api-save-lock.test.ts +2 -1
- package/test/utils/assistant-text.test.ts +64 -0
- package/test/utils/streaming-text.test.ts +89 -0
|
@@ -858,9 +858,9 @@ export function ChatView({ variant = "default" }: ChatViewProps) {
|
|
|
858
858
|
data-no-camera-drag={isGameModal || undefined}
|
|
859
859
|
style={{ zIndex: 1 }}
|
|
860
860
|
>
|
|
861
|
-
{chatPendingImages.map((img,
|
|
861
|
+
{chatPendingImages.map((img, imgIdx) => (
|
|
862
862
|
<div
|
|
863
|
-
key={`${img.name}-${
|
|
863
|
+
key={`${img.name}-${img.data}`}
|
|
864
864
|
className="relative group w-16 h-16 shrink-0"
|
|
865
865
|
>
|
|
866
866
|
<img
|
|
@@ -872,7 +872,7 @@ export function ChatView({ variant = "default" }: ChatViewProps) {
|
|
|
872
872
|
type="button"
|
|
873
873
|
title={t("chatview.RemoveImage")}
|
|
874
874
|
aria-label={`Remove image ${img.name}`}
|
|
875
|
-
onClick={() => removeImage(
|
|
875
|
+
onClick={() => removeImage(imgIdx)}
|
|
876
876
|
className="absolute -top-1.5 -right-1.5 w-4 h-4 rounded-full bg-danger text-white text-[10px] flex items-center justify-center opacity-100 sm:opacity-0 sm:group-hover:opacity-100 focus-visible:opacity-100 transition-opacity cursor-pointer"
|
|
877
877
|
>
|
|
878
878
|
×
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
* 2. Secrets (modal)
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { useCallback, useEffect, useState } from "react";
|
|
10
9
|
import {
|
|
11
10
|
WALLET_RPC_PROVIDER_OPTIONS,
|
|
12
11
|
type WalletRpcSelections,
|
|
13
12
|
} from "@elizaos/autonomous/contracts/wallet";
|
|
13
|
+
import { useCallback, useEffect, useState } from "react";
|
|
14
14
|
import { client } from "../api";
|
|
15
15
|
import {
|
|
16
16
|
ConfigRenderer,
|
|
@@ -468,18 +468,19 @@ export function ConfigPageView({ embedded = false }: { embedded?: boolean }) {
|
|
|
468
468
|
}, []);
|
|
469
469
|
|
|
470
470
|
/* ── RPC provider selection state ──────────────────────────────────── */
|
|
471
|
+
const initialRpc = resolveInitialWalletRpcSelections(walletConfig);
|
|
471
472
|
const [selectedEvmRpc, setSelectedEvmRpc] =
|
|
472
|
-
useState<WalletRpcSelections["evm"]>(
|
|
473
|
+
useState<WalletRpcSelections["evm"]>(initialRpc.evm);
|
|
473
474
|
const [selectedBscRpc, setSelectedBscRpc] =
|
|
474
|
-
useState<WalletRpcSelections["bsc"]>(
|
|
475
|
+
useState<WalletRpcSelections["bsc"]>(initialRpc.bsc);
|
|
475
476
|
const [selectedSolanaRpc, setSelectedSolanaRpc] =
|
|
476
|
-
useState<WalletRpcSelections["solana"]>(
|
|
477
|
+
useState<WalletRpcSelections["solana"]>(initialRpc.solana);
|
|
477
478
|
|
|
478
479
|
useEffect(() => {
|
|
479
|
-
const
|
|
480
|
-
setSelectedEvmRpc(
|
|
481
|
-
setSelectedBscRpc(
|
|
482
|
-
setSelectedSolanaRpc(
|
|
480
|
+
const selections = resolveInitialWalletRpcSelections(walletConfig);
|
|
481
|
+
setSelectedEvmRpc(selections.evm);
|
|
482
|
+
setSelectedBscRpc(selections.bsc);
|
|
483
|
+
setSelectedSolanaRpc(selections.solana);
|
|
483
484
|
}, [walletConfig]);
|
|
484
485
|
|
|
485
486
|
const handleWalletSaveAll = useCallback(() => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { useApp } from "../state";
|
|
2
1
|
import {
|
|
3
2
|
DropdownMenu,
|
|
4
3
|
DropdownMenuContent,
|
|
@@ -6,6 +5,7 @@ import {
|
|
|
6
5
|
DropdownMenuTrigger,
|
|
7
6
|
} from "@elizaos/ui";
|
|
8
7
|
import { useEffect, useRef, useState } from "react";
|
|
8
|
+
import { useApp } from "../state";
|
|
9
9
|
import { ConversationListItem } from "./conversations/ConversationListItem";
|
|
10
10
|
|
|
11
11
|
type ConversationsSidebarVariant = "default" | "game-modal";
|
|
@@ -989,15 +989,15 @@ export function CustomActionEditor({
|
|
|
989
989
|
{t("customactioneditor.AddParameter")}
|
|
990
990
|
</button>
|
|
991
991
|
</div>
|
|
992
|
-
{parameters.map((param,
|
|
992
|
+
{parameters.map((param, paramIdx) => (
|
|
993
993
|
<div
|
|
994
|
-
key={`${param.name}-${
|
|
994
|
+
key={`${param.name}-${param.description ?? ""}`}
|
|
995
995
|
className="flex gap-2 items-start"
|
|
996
996
|
>
|
|
997
997
|
<input
|
|
998
998
|
type="text"
|
|
999
999
|
value={param.name}
|
|
1000
|
-
onChange={(e) => updateParameter(
|
|
1000
|
+
onChange={(e) => updateParameter(paramIdx, "name", e.target.value)}
|
|
1001
1001
|
placeholder={t("customactioneditor.paramName")}
|
|
1002
1002
|
className="w-32 bg-surface border border-border px-2 py-1.5 text-sm text-txt placeholder:text-muted/50 outline-none focus:border-accent"
|
|
1003
1003
|
/>
|
|
@@ -1005,7 +1005,7 @@ export function CustomActionEditor({
|
|
|
1005
1005
|
type="text"
|
|
1006
1006
|
value={param.description}
|
|
1007
1007
|
onChange={(e) =>
|
|
1008
|
-
updateParameter(
|
|
1008
|
+
updateParameter(paramIdx, "description", e.target.value)
|
|
1009
1009
|
}
|
|
1010
1010
|
placeholder={t("skillsview.Description")}
|
|
1011
1011
|
className="flex-1 bg-surface border border-border px-2 py-1.5 text-sm text-txt placeholder:text-muted/50 outline-none focus:border-accent"
|
|
@@ -1015,7 +1015,7 @@ export function CustomActionEditor({
|
|
|
1015
1015
|
type="checkbox"
|
|
1016
1016
|
checked={param.required}
|
|
1017
1017
|
onChange={(e) =>
|
|
1018
|
-
updateParameter(
|
|
1018
|
+
updateParameter(paramIdx, "required", e.target.checked)
|
|
1019
1019
|
}
|
|
1020
1020
|
className="cursor-pointer"
|
|
1021
1021
|
/>
|
|
@@ -1024,7 +1024,7 @@ export function CustomActionEditor({
|
|
|
1024
1024
|
</span>
|
|
1025
1025
|
<button
|
|
1026
1026
|
type="button"
|
|
1027
|
-
onClick={() => removeParameter(
|
|
1027
|
+
onClick={() => removeParameter(paramIdx)}
|
|
1028
1028
|
className="px-2 text-muted hover:text-txt cursor-pointer"
|
|
1029
1029
|
>
|
|
1030
1030
|
{t("bugreportmodal.Times")}
|
|
@@ -15,7 +15,10 @@ import { useApp } from "@elizaos/app-core/state";
|
|
|
15
15
|
import { confirmDesktopAction } from "@elizaos/app-core/utils";
|
|
16
16
|
import { Button, Input } from "@elizaos/ui";
|
|
17
17
|
import { useCallback, useEffect, useState } from "react";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
parsePositiveFloat,
|
|
20
|
+
parsePositiveInteger,
|
|
21
|
+
} from "../utils/number-parsing";
|
|
19
22
|
|
|
20
23
|
const TRAINING_EVENT_KINDS = new Set<TrainingStreamEvent["kind"]>([
|
|
21
24
|
"job_started",
|
|
@@ -1048,9 +1051,9 @@ export function FineTuningView() {
|
|
|
1048
1051
|
{t("finetuningview.NoLiveEventsYet")}
|
|
1049
1052
|
</div>
|
|
1050
1053
|
) : (
|
|
1051
|
-
trainingEvents.map((event
|
|
1054
|
+
trainingEvents.map((event) => (
|
|
1052
1055
|
<div
|
|
1053
|
-
key={`${event.ts}-${event.kind}-${
|
|
1056
|
+
key={`${event.ts}-${event.kind}-${String(event.message ?? "")}`}
|
|
1054
1057
|
className="px-2 py-1.5 border-b border-border text-xs"
|
|
1055
1058
|
>
|
|
1056
1059
|
<span className="font-mono text-muted mr-2">
|
|
@@ -261,7 +261,7 @@ export function HeartbeatsView() {
|
|
|
261
261
|
triggersLoading = false,
|
|
262
262
|
triggersSaving = false,
|
|
263
263
|
triggerRunsById = {},
|
|
264
|
-
triggerHealth = null,
|
|
264
|
+
triggerHealth: _triggerHealth = null,
|
|
265
265
|
triggerError = null,
|
|
266
266
|
loadTriggers = async () => {},
|
|
267
267
|
createTrigger = async () => null,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { useApp } from "@elizaos/app-core/state";
|
|
9
9
|
import { useCallback, useState } from "react";
|
|
10
10
|
import { TradePanel } from "./BscTradePanel";
|
|
11
|
-
import { CHAIN_CONFIGS,
|
|
11
|
+
import { CHAIN_CONFIGS, type ChainKey, resolveChainKey } from "./chainConfig";
|
|
12
12
|
import {
|
|
13
13
|
BSC_GAS_THRESHOLD,
|
|
14
14
|
loadTrackedBscTokens,
|
|
@@ -168,7 +168,7 @@ export function InventoryView({ inModal }: { inModal?: boolean } = {}) {
|
|
|
168
168
|
: null;
|
|
169
169
|
|
|
170
170
|
const headerWarning =
|
|
171
|
-
chainFocus !== "all" && cfg?.legacyCustomChains?.includes(chainFocus)
|
|
171
|
+
chainFocus !== "all" && cfg?.legacyCustomChains?.includes(chainFocus as unknown as "evm" | "bsc" | "solana")
|
|
172
172
|
? {
|
|
173
173
|
title: `${
|
|
174
174
|
focusedChainLabel ??
|
|
@@ -24,6 +24,7 @@ export function LoadingScreen({
|
|
|
24
24
|
vrmUrl,
|
|
25
25
|
}: LoadingScreenProps) {
|
|
26
26
|
const [vrmCached, setVrmCached] = useState(false);
|
|
27
|
+
const [fetchProgress, setFetchProgress] = useState(0);
|
|
27
28
|
const [, setRuntimeElapsedSeconds] = useState(0);
|
|
28
29
|
|
|
29
30
|
useEffect(() => {
|
|
@@ -40,16 +41,45 @@ export function LoadingScreen({
|
|
|
40
41
|
useEffect(() => {
|
|
41
42
|
if (!vrmUrl) return;
|
|
42
43
|
const controller = new AbortController();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
|
|
45
|
+
(async () => {
|
|
46
|
+
try {
|
|
47
|
+
const response = await fetch(vrmUrl, { signal: controller.signal });
|
|
48
|
+
const contentLength = Number(response.headers.get("content-length") || 0);
|
|
49
|
+
|
|
50
|
+
if (!contentLength || !response.body) {
|
|
51
|
+
setVrmCached(true);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const reader = response.body.getReader();
|
|
56
|
+
let received = 0;
|
|
57
|
+
|
|
58
|
+
for (;;) {
|
|
59
|
+
const { done, value } = await reader.read();
|
|
60
|
+
if (done) break;
|
|
61
|
+
received += value.byteLength;
|
|
62
|
+
setFetchProgress(Math.min(received / contentLength, 1));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setVrmCached(true);
|
|
66
|
+
} catch {
|
|
46
67
|
// Non-blocking — VRM will load normally later.
|
|
47
|
-
}
|
|
68
|
+
}
|
|
69
|
+
})();
|
|
70
|
+
|
|
48
71
|
return () => controller.abort();
|
|
49
72
|
}, [vrmUrl]);
|
|
50
73
|
|
|
51
74
|
const meta = PHASE_META[phase];
|
|
52
|
-
|
|
75
|
+
let progress: number;
|
|
76
|
+
if (vrmCached) {
|
|
77
|
+
progress = Math.max(meta.progress, 80);
|
|
78
|
+
} else if (fetchProgress > 0) {
|
|
79
|
+
progress = Math.max(meta.progress, Math.round(55 + fetchProgress * 25));
|
|
80
|
+
} else {
|
|
81
|
+
progress = meta.progress;
|
|
82
|
+
}
|
|
53
83
|
const label = vrmCached && phase !== "ready" ? "Loading avatar" : meta.label;
|
|
54
84
|
|
|
55
85
|
return (
|
|
@@ -64,7 +94,10 @@ export function LoadingScreen({
|
|
|
64
94
|
<div className="loading-screen__progress-track">
|
|
65
95
|
<div
|
|
66
96
|
className="loading-screen__progress-fill"
|
|
67
|
-
style={{
|
|
97
|
+
style={{
|
|
98
|
+
width: `${progress}%`,
|
|
99
|
+
transition: "width 1.5s ease-out",
|
|
100
|
+
}}
|
|
68
101
|
/>
|
|
69
102
|
</div>
|
|
70
103
|
<div className="loading-screen__percent">{progress} %</div>
|
|
@@ -12,11 +12,11 @@ import { useEffect } from "react";
|
|
|
12
12
|
import { VrmStage } from "./companion/VrmStage";
|
|
13
13
|
import { ActivateStep } from "./onboarding/ActivateStep";
|
|
14
14
|
import { ConnectionStep } from "./onboarding/ConnectionStep";
|
|
15
|
+
import { IdentityStep } from "./onboarding/IdentityStep";
|
|
15
16
|
import { OnboardingPanel } from "./onboarding/OnboardingPanel";
|
|
16
17
|
import { OnboardingStepNav } from "./onboarding/OnboardingStepNav";
|
|
17
18
|
import { PermissionsStep } from "./onboarding/PermissionsStep";
|
|
18
19
|
import { RpcStep } from "./onboarding/RpcStep";
|
|
19
|
-
import { IdentityStep } from "./onboarding/IdentityStep";
|
|
20
20
|
import { WakeUpStep } from "./onboarding/WakeUpStep";
|
|
21
21
|
|
|
22
22
|
export function OnboardingWizard() {
|
|
@@ -1949,6 +1949,8 @@ function PluginListView({ label, mode = "all", inModal }: PluginListViewProps) {
|
|
|
1949
1949
|
setConnectorSelectedId(pluginId);
|
|
1950
1950
|
setConnectorExpandedIds((prev) => {
|
|
1951
1951
|
if (desktopConnectorLayout) {
|
|
1952
|
+
// Accordion: toggle off if already open, otherwise open this one only
|
|
1953
|
+
if (prev.has(pluginId)) return new Set();
|
|
1952
1954
|
return new Set([pluginId]);
|
|
1953
1955
|
}
|
|
1954
1956
|
const next = new Set(prev);
|
|
@@ -2725,6 +2727,10 @@ function PluginListView({ label, mode = "all", inModal }: PluginListViewProps) {
|
|
|
2725
2727
|
<div className="relative flex-1 min-w-[220px]">
|
|
2726
2728
|
<Input
|
|
2727
2729
|
type="text"
|
|
2730
|
+
name="plugin-search"
|
|
2731
|
+
autoComplete="off"
|
|
2732
|
+
data-1p-ignore
|
|
2733
|
+
data-lpignore="true"
|
|
2728
2734
|
className="w-full bg-card/60 backdrop-blur-md shadow-inner pr-8 h-9 rounded-xl focus-visible:ring-accent border-border/40"
|
|
2729
2735
|
placeholder={searchPlaceholder}
|
|
2730
2736
|
value={pluginSearch}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { GlobalEmoteOverlay } from "./GlobalEmoteOverlay";
|
|
1
2
|
import {
|
|
2
3
|
BugReportModal,
|
|
3
4
|
CommandPalette,
|
|
4
5
|
RestartBanner,
|
|
5
6
|
ShortcutsOverlay,
|
|
6
7
|
} from "./index";
|
|
7
|
-
import { GlobalEmoteOverlay } from "./GlobalEmoteOverlay";
|
|
8
8
|
|
|
9
9
|
export interface ActionNotice {
|
|
10
10
|
text: string;
|
|
@@ -16,10 +16,7 @@ import {
|
|
|
16
16
|
type VoiceMode,
|
|
17
17
|
type VoiceProvider,
|
|
18
18
|
} from "../api";
|
|
19
|
-
import {
|
|
20
|
-
getSwabblePlugin,
|
|
21
|
-
type SwabbleConfig,
|
|
22
|
-
} from "../bridge/native-plugins";
|
|
19
|
+
import { getSwabblePlugin, type SwabbleConfig } from "../bridge/native-plugins";
|
|
23
20
|
import { dispatchWindowEvent, VOICE_CONFIG_UPDATED_EVENT } from "../events";
|
|
24
21
|
import { useTimeout } from "../hooks";
|
|
25
22
|
import { useApp } from "../state";
|
|
@@ -165,7 +162,9 @@ function WakeWordSection({
|
|
|
165
162
|
await getSwabblePlugin().stop();
|
|
166
163
|
setEnabled(false);
|
|
167
164
|
} else {
|
|
168
|
-
const result = await getSwabblePlugin().start({
|
|
165
|
+
const result = await getSwabblePlugin().start({
|
|
166
|
+
config: buildConfig(),
|
|
167
|
+
});
|
|
169
168
|
if (result.started) setEnabled(true);
|
|
170
169
|
}
|
|
171
170
|
} catch {
|
|
@@ -10,6 +10,15 @@ import type {
|
|
|
10
10
|
SplatMesh as SparkSplatMesh,
|
|
11
11
|
} from "@sparkjsdev/spark";
|
|
12
12
|
import * as THREE from "three";
|
|
13
|
+
|
|
14
|
+
/** Three.js NodeMaterial exposes emissiveNode/opacityNode but they are not in public MeshStandardMaterial types. */
|
|
15
|
+
interface MeshStandardMaterialWithNodeProps {
|
|
16
|
+
// biome-ignore lint/suspicious/noExplicitAny: THREE node types are not in public @types/three
|
|
17
|
+
emissiveNode?: any;
|
|
18
|
+
// biome-ignore lint/suspicious/noExplicitAny: THREE node types are not in public @types/three
|
|
19
|
+
opacityNode?: any;
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
14
23
|
import { MeshoptDecoder } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
15
24
|
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
@@ -2009,6 +2018,12 @@ export class VrmEngine {
|
|
|
2009
2018
|
}
|
|
2010
2019
|
activeEmote?.fadeOut(fadeDuration);
|
|
2011
2020
|
}
|
|
2021
|
+
|
|
2022
|
+
/** Play a one-shot wave greeting after the VRM becomes visible. */
|
|
2023
|
+
playWaveGreeting(): void {
|
|
2024
|
+
this.playEmote("animations/emotes/waving-both-hands.glb.gz", 3, false);
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2012
2027
|
async loadVrmFromUrl(url: string, name?: string): Promise<void> {
|
|
2013
2028
|
await this.whenReady();
|
|
2014
2029
|
if (!this.scene) throw new Error("VrmEngine not initialized");
|
|
@@ -2119,9 +2134,13 @@ export class VrmEngine {
|
|
|
2119
2134
|
await this.loadAndPlayIdle(vrm);
|
|
2120
2135
|
if (!this.loadingAborted && this.vrm === vrm) {
|
|
2121
2136
|
this.vrmReady = true;
|
|
2137
|
+
// Let the idle animation settle into a natural pose before revealing
|
|
2138
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
2139
|
+
if (this.loadingAborted || this.vrm !== vrm) return;
|
|
2122
2140
|
await this.playTeleportReveal(vrm);
|
|
2123
2141
|
vrm.scene.visible = true;
|
|
2124
2142
|
this.startPendingWorldReveal(true);
|
|
2143
|
+
this.playWaveGreeting();
|
|
2125
2144
|
}
|
|
2126
2145
|
} catch {
|
|
2127
2146
|
if (!this.loadingAborted && this.vrm === vrm) {
|
|
@@ -2155,8 +2174,8 @@ export class VrmEngine {
|
|
|
2155
2174
|
appliedNodeDissolve = true;
|
|
2156
2175
|
mat.userData._dissolveApplied = true;
|
|
2157
2176
|
mat.userData._origOpacityNode = mat.opacityNode ?? null;
|
|
2158
|
-
|
|
2159
|
-
|
|
2177
|
+
mat.userData._origEmissiveNode =
|
|
2178
|
+
(mat as MeshStandardMaterialWithNodeProps).emissiveNode ?? null;
|
|
2160
2179
|
mat.userData._origAlphaTest = mat.alphaTest;
|
|
2161
2180
|
|
|
2162
2181
|
// World-space Y from TSL
|
|
@@ -2221,10 +2240,9 @@ export class VrmEngine {
|
|
|
2221
2240
|
? origOpacity.mul(dissolveAlpha)
|
|
2222
2241
|
: dissolveAlpha;
|
|
2223
2242
|
|
|
2224
|
-
|
|
2225
|
-
const origEmissive =
|
|
2226
|
-
|
|
2227
|
-
(mat as any).emissiveNode = origEmissive
|
|
2243
|
+
const matWithEmissive = mat as MeshStandardMaterialWithNodeProps;
|
|
2244
|
+
const origEmissive = matWithEmissive.emissiveNode;
|
|
2245
|
+
matWithEmissive.emissiveNode = origEmissive
|
|
2228
2246
|
? origEmissive.add(emissiveBoost)
|
|
2229
2247
|
: emissiveBoost;
|
|
2230
2248
|
|
|
@@ -2429,7 +2447,7 @@ if (teleportNoise < teleportRatio) discard;
|
|
|
2429
2447
|
mat.userData._origOpacityNode ?? null;
|
|
2430
2448
|
}
|
|
2431
2449
|
if (mat.userData._origEmissiveNode !== undefined) {
|
|
2432
|
-
(mat as
|
|
2450
|
+
(mat as MeshStandardMaterialWithNodeProps).emissiveNode =
|
|
2433
2451
|
mat.userData._origEmissiveNode ?? null;
|
|
2434
2452
|
}
|
|
2435
2453
|
mat.alphaTest = mat.userData._origAlphaTest ?? 0;
|
package/src/components/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from "./ApiKeyConfig";
|
|
2
1
|
export * from "./AdvancedPageView";
|
|
3
2
|
export * from "./AgentActivityBox";
|
|
3
|
+
export * from "./ApiKeyConfig";
|
|
4
4
|
export * from "./AppsPageView";
|
|
5
5
|
export * from "./AppsView";
|
|
6
6
|
export * from "./AvatarLoader";
|
|
@@ -25,15 +25,20 @@ export * from "./ConfigPageView";
|
|
|
25
25
|
export * from "./ConfigSaveFooter";
|
|
26
26
|
export * from "./ConfirmModal";
|
|
27
27
|
export * from "./ConnectionFailedBanner";
|
|
28
|
-
export * from "./ConversationsSidebar";
|
|
29
28
|
export * from "./ConnectorsPageView";
|
|
30
|
-
export * from "./
|
|
29
|
+
export * from "./ConversationsSidebar";
|
|
31
30
|
export * from "./CustomActionEditor";
|
|
32
31
|
export * from "./CustomActionsPanel";
|
|
33
32
|
export * from "./CustomActionsView";
|
|
33
|
+
export * from "./chainConfig";
|
|
34
|
+
export * from "./companion-shell-styles";
|
|
35
|
+
export * from "./confirm-delete-control";
|
|
36
|
+
export * from "./conversations/ConversationListItem";
|
|
37
|
+
export * from "./conversations/conversation-utils";
|
|
34
38
|
export * from "./DatabasePageView";
|
|
35
39
|
export * from "./DatabaseView";
|
|
36
40
|
export * from "./ElizaCloudDashboard";
|
|
41
|
+
export * from "./ElizaCloudDashboard";
|
|
37
42
|
export * from "./EmotePicker";
|
|
38
43
|
export * from "./ErrorBoundary";
|
|
39
44
|
export * from "./FineTuningView";
|
|
@@ -41,8 +46,8 @@ export * from "./format";
|
|
|
41
46
|
export * from "./GameView";
|
|
42
47
|
export * from "./GameViewOverlay";
|
|
43
48
|
export * from "./GlobalEmoteOverlay";
|
|
44
|
-
export * from "./HeartbeatsView";
|
|
45
49
|
export * from "./Header";
|
|
50
|
+
export * from "./HeartbeatsView";
|
|
46
51
|
export * from "./InventoryView";
|
|
47
52
|
export * from "./KnowledgeView";
|
|
48
53
|
export * from "./knowledge-upload-image";
|
|
@@ -56,7 +61,6 @@ export * from "./labels";
|
|
|
56
61
|
export * from "./MediaGalleryView";
|
|
57
62
|
export * from "./MediaSettingsSection";
|
|
58
63
|
export * from "./MessageContent";
|
|
59
|
-
export * from "./ElizaCloudDashboard";
|
|
60
64
|
export * from "./OnboardingWizard";
|
|
61
65
|
export * from "./PairingView";
|
|
62
66
|
export * from "./PermissionsSection";
|
|
@@ -78,9 +82,9 @@ export * from "./SystemWarningBanner";
|
|
|
78
82
|
export { useSharedCompanionScene } from "./shared-companion-scene-context";
|
|
79
83
|
export * from "./skeletons";
|
|
80
84
|
export * from "./ThemeToggle";
|
|
81
|
-
export * from "./TriggersView";
|
|
82
85
|
export * from "./TrajectoriesView";
|
|
83
86
|
export * from "./TrajectoryDetailView";
|
|
87
|
+
export * from "./TriggersView";
|
|
84
88
|
export * from "./trajectory-format";
|
|
85
89
|
export * from "./ui-badges";
|
|
86
90
|
export * from "./ui-switch";
|
|
@@ -88,7 +92,3 @@ export * from "./VectorBrowserView";
|
|
|
88
92
|
export * from "./VoiceConfigView";
|
|
89
93
|
export * from "./VrmStage";
|
|
90
94
|
export * from "./WhatsAppQrOverlay";
|
|
91
|
-
export * from "./chainConfig";
|
|
92
|
-
export * from "./companion-shell-styles";
|
|
93
|
-
export * from "./conversations/ConversationListItem";
|
|
94
|
-
export * from "./conversations/conversation-utils";
|
|
@@ -131,11 +131,11 @@ export function TokensTable({
|
|
|
131
131
|
</tr>
|
|
132
132
|
</thead>
|
|
133
133
|
<tbody>
|
|
134
|
-
{visibleRows.map((row
|
|
134
|
+
{visibleRows.map((row) => {
|
|
135
135
|
const contractAddress = row.contractAddress;
|
|
136
136
|
return (
|
|
137
137
|
<tr
|
|
138
|
-
key={`${row.chain}-${row.symbol}-${
|
|
138
|
+
key={`${row.chain}-${row.symbol}-${row.contractAddress ?? ""}`}
|
|
139
139
|
className="border-b border-border last:border-b-0 hover:bg-bg-hover transition-colors"
|
|
140
140
|
>
|
|
141
141
|
{/* Logo */}
|
|
@@ -2,15 +2,13 @@ import { getVrmPreviewUrl, useApp } from "@elizaos/app-core/state";
|
|
|
2
2
|
import { useCallback, useEffect } from "react";
|
|
3
3
|
|
|
4
4
|
/** Maps catchphrases → character metadata for onboarding. */
|
|
5
|
-
const IDENTITY_PRESETS: Record<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"hehe~": { name: "Aya", avatarIndex: 4 },
|
|
13
|
-
};
|
|
5
|
+
const IDENTITY_PRESETS: Record<string, { name: string; avatarIndex: number }> =
|
|
6
|
+
{
|
|
7
|
+
"Noted.": { name: "Rin", avatarIndex: 1 },
|
|
8
|
+
"uwu~": { name: "Ai", avatarIndex: 2 },
|
|
9
|
+
"lol k": { name: "Anzu", avatarIndex: 3 },
|
|
10
|
+
"hehe~": { name: "Aya", avatarIndex: 4 },
|
|
11
|
+
};
|
|
14
12
|
|
|
15
13
|
export function IdentityStep() {
|
|
16
14
|
const {
|
|
@@ -18,7 +16,7 @@ export function IdentityStep() {
|
|
|
18
16
|
onboardingStyle,
|
|
19
17
|
handleOnboardingNext,
|
|
20
18
|
setState,
|
|
21
|
-
t,
|
|
19
|
+
t: _t,
|
|
22
20
|
} = useApp();
|
|
23
21
|
|
|
24
22
|
const styles = onboardingOptions?.styles ?? [];
|
|
@@ -47,9 +45,7 @@ export function IdentityStep() {
|
|
|
47
45
|
|
|
48
46
|
return (
|
|
49
47
|
<>
|
|
50
|
-
<div className="onboarding-section-title">
|
|
51
|
-
Choose Your Agent
|
|
52
|
-
</div>
|
|
48
|
+
<div className="onboarding-section-title">Choose Your Agent</div>
|
|
53
49
|
<div className="onboarding-divider">
|
|
54
50
|
<div className="onboarding-divider-diamond" />
|
|
55
51
|
</div>
|
|
@@ -120,7 +120,7 @@ export function ShellHeaderControls({
|
|
|
120
120
|
>
|
|
121
121
|
<div className="flex shrink-0 items-center">
|
|
122
122
|
<fieldset
|
|
123
|
-
className="inline-flex items-center gap-0.5 rounded-xl border border-border/60 bg-transparent p-0.5 shadow-sm dark:border-border
|
|
123
|
+
className="inline-flex items-center gap-0.5 rounded-xl border border-border/60 bg-transparent p-0.5 shadow-sm dark:border-border dark:bg-transparent"
|
|
124
124
|
data-testid="ui-shell-toggle"
|
|
125
125
|
aria-label="Switch shell view"
|
|
126
126
|
>
|
|
@@ -98,17 +98,14 @@ function PasswordFieldInner({ fp: props }: { fp: FieldRenderProps }) {
|
|
|
98
98
|
|
|
99
99
|
const [visible, setVisible] = useState(false);
|
|
100
100
|
const [busy, setBusy] = useState(false);
|
|
101
|
+
const [fieldValue, setFieldValue] = useState("");
|
|
101
102
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
102
103
|
const onReveal = props.onReveal;
|
|
103
104
|
|
|
104
105
|
const handleToggle = useCallback(async () => {
|
|
105
|
-
const input = inputRef.current;
|
|
106
|
-
if (!input) return;
|
|
107
|
-
|
|
108
106
|
if (visible) {
|
|
109
|
-
//
|
|
107
|
+
// Hide — just toggle visibility, value stays in React state
|
|
110
108
|
setVisible(false);
|
|
111
|
-
input.value = "";
|
|
112
109
|
return;
|
|
113
110
|
}
|
|
114
111
|
|
|
@@ -119,13 +116,14 @@ function PasswordFieldInner({ fp: props }: { fp: FieldRenderProps }) {
|
|
|
119
116
|
setBusy(false);
|
|
120
117
|
if (realValue != null) {
|
|
121
118
|
setVisible(true);
|
|
122
|
-
|
|
119
|
+
setFieldValue(realValue);
|
|
120
|
+
props.onChange(realValue);
|
|
123
121
|
}
|
|
124
122
|
} else {
|
|
125
123
|
// Fallback: just toggle type (shows whatever is in the input)
|
|
126
124
|
setVisible(true);
|
|
127
125
|
}
|
|
128
|
-
}, [visible, onReveal]);
|
|
126
|
+
}, [visible, onReveal, props]);
|
|
129
127
|
|
|
130
128
|
return (
|
|
131
129
|
<div className="flex">
|
|
@@ -133,11 +131,12 @@ function PasswordFieldInner({ fp: props }: { fp: FieldRenderProps }) {
|
|
|
133
131
|
ref={inputRef}
|
|
134
132
|
className="flex-1 px-3 py-2 border border-[var(--border)] border-r-0 bg-[var(--card)] text-[13px] font-[var(--mono)] transition-all focus:border-[var(--accent)] focus:outline-none focus:ring-1 focus:ring-[var(--accent)] box-border h-[36px] rounded-l-sm placeholder:text-[var(--muted)] placeholder:opacity-60"
|
|
135
133
|
type={visible ? "text" : "password"}
|
|
136
|
-
|
|
134
|
+
value={fieldValue}
|
|
137
135
|
placeholder={placeholder}
|
|
138
136
|
data-config-key={props.key}
|
|
139
137
|
data-field-type="password"
|
|
140
138
|
onChange={(e) => {
|
|
139
|
+
setFieldValue(e.target.value);
|
|
141
140
|
props.onChange(e.target.value);
|
|
142
141
|
fireAction(props, "change");
|
|
143
142
|
}}
|
package/src/config/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export * from "./config-catalog";
|
|
2
2
|
export * from "./config-renderer";
|
|
3
|
-
export * from "./ui-spec";
|
|
4
3
|
export {
|
|
5
|
-
UiRenderer,
|
|
6
|
-
type UiRendererProps,
|
|
7
4
|
evaluateUiVisibility,
|
|
8
5
|
getSupportedComponents,
|
|
9
6
|
runValidation as runUiValidation,
|
|
10
7
|
sanitizeLinkHref,
|
|
8
|
+
UiRenderer,
|
|
9
|
+
type UiRendererProps,
|
|
11
10
|
} from "./ui-renderer";
|
|
11
|
+
export * from "./ui-spec";
|
|
@@ -850,9 +850,11 @@ export function useVoiceChat(options: VoiceChatOptions): VoiceChatState {
|
|
|
850
850
|
enabledRef.current = false;
|
|
851
851
|
|
|
852
852
|
if (sttBackendRef.current === "talkmode") {
|
|
853
|
-
await getTalkModePlugin()
|
|
854
|
-
|
|
855
|
-
|
|
853
|
+
await getTalkModePlugin()
|
|
854
|
+
.stop()
|
|
855
|
+
.catch(() => {
|
|
856
|
+
/* ignore */
|
|
857
|
+
});
|
|
856
858
|
await new Promise((resolve) =>
|
|
857
859
|
window.setTimeout(resolve, TALKMODE_STOP_SETTLE_MS),
|
|
858
860
|
);
|