Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 9 additions & 18 deletions apps/dashboard/src/app/nebula-app/(app)/api/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,33 @@ import { NEXT_PUBLIC_NEBULA_URL } from "@/constants/env";
// TODO - copy the source of this library to dashboard
import { stream } from "fetch-event-stream";
import type { NebulaTxData } from "../components/Chats";
import type { ExecuteConfig } from "./types";

export type ContextFilters = {
chainIds?: string[];
contractAddresses?: string[];
walletAddresses?: string[];
export type NebulaContext = {
chainIds: string[] | null;
walletAddress: string | null;
};

export async function promptNebula(params: {
message: string;
sessionId: string;
config: ExecuteConfig | null;
authToken: string;
handleStream: (res: ChatStreamedResponse) => void;
abortController: AbortController;
contextFilters: undefined | ContextFilters;
context: undefined | NebulaContext;
}) {
const body: Record<string, string | boolean | object> = {
message: params.message,
user_id: "default-user",
session_id: params.sessionId,
stream: true,
session_id: params.sessionId,
};

if (params.contextFilters) {
body.context_filter = {
chain_ids: params.contextFilters.chainIds || [],
contract_addresses: params.contextFilters.contractAddresses || [],
wallet_addresses: params.contextFilters.walletAddresses || [],
if (params.context) {
body.context = {
chain_ids: params.context.chainIds || [],
wallet_address: params.context.walletAddress,
};
}

if (params.config) {
body.execute_config = params.config;
}

const events = await stream(`${NEXT_PUBLIC_NEBULA_URL}/chat`, {
method: "POST",
headers: {
Expand Down
39 changes: 11 additions & 28 deletions apps/dashboard/src/app/nebula-app/(app)/api/session.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
import { NEXT_PUBLIC_NEBULA_URL } from "@/constants/env";
import { fetchWithAuthToken } from "../../../../utils/fetchWithAuthToken";
import type { ContextFilters } from "./chat";
import type { NebulaContext } from "./chat";
import type {
DeletedSessionInfo,
ExecuteConfig,
SessionInfo,
TruncatedSessionInfo,
UpdatedSessionInfo,
} from "./types";

// TODO - get the spec for return types on /session POST and PUT

export async function createSession(params: {
authToken: string;
config: ExecuteConfig | null;
contextFilters: ContextFilters | undefined;
context: NebulaContext | undefined;
}) {
const body: Record<string, string | boolean | object> = {
can_execute: !!params.config,
};
if (params.config) {
body.execute_config = params.config;
}
const body: Record<string, string | boolean | object> = {};

if (params.contextFilters) {
body.context_filter = {
chain_ids: params.contextFilters.chainIds || [],
contract_addresses: params.contextFilters.contractAddresses || [],
wallet_addresses: params.contextFilters.walletAddresses || [],
if (params.context) {
body.context = {
chain_ids: params.context.chainIds || [],
wallet_address: params.context.walletAddress,
};
}

Expand All @@ -48,22 +38,15 @@ export async function createSession(params: {

export async function updateSession(params: {
authToken: string;
config: ExecuteConfig | null;
sessionId: string;
contextFilters: ContextFilters | undefined;
contextFilters: NebulaContext | undefined;
}) {
const body: Record<string, string | boolean | object> = {
can_execute: !!params.config,
};
if (params.config) {
body.execute_config = params.config;
}
const body: Record<string, string | boolean | object> = {};

if (params.contextFilters) {
body.context_filter = {
body.context = {
chain_ids: params.contextFilters.chainIds || [],
contract_addresses: params.contextFilters.contractAddresses || [],
wallet_addresses: params.contextFilters.walletAddresses || [],
wallet_address: params.contextFilters.walletAddress,
};
}

Expand Down
30 changes: 3 additions & 27 deletions apps/dashboard/src/app/nebula-app/(app)/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,6 @@
type EngineConfig = {
mode: "engine";
engine_url: string;
engine_authorization_token: string;
engine_backend_wallet_address: string;
};

type SessionKeyConfig = {
mode: "session_key";
smart_account_address: string;
smart_account_factory_address: string;
smart_account_session_key: string;
};

type ClientConfig = {
mode: "client";
signer_wallet_address: string;
};

export type ExecuteConfig = EngineConfig | SessionKeyConfig | ClientConfig;

type SessionContextFilter = {
chain_ids: string[] | null;
contract_addresses: string[] | null;
wallet_addresses: string[] | null;
wallet_address: string | null;
};

export type SessionInfo = {
Expand All @@ -31,7 +9,6 @@ export type SessionInfo = {
modal_name: string;
archive_at: string | null;
can_execute: boolean;
execute_config: ExecuteConfig | null;
created_at: string;
deleted_at: string | null;
history: Array<{
Expand All @@ -43,7 +20,7 @@ export type SessionInfo = {
archived_at: string | null;
title: string | null;
is_public: boolean | null;
context_filter: SessionContextFilter | null;
context: SessionContextFilter | null;
// memory
// action: array<object> | null; <-- type of this is not available on https://nebula-api.thirdweb-dev.com/docs#/default/get_session_session__session_id__get
};
Expand All @@ -52,8 +29,7 @@ export type UpdatedSessionInfo = {
title: string;
modal_name: string;
account_id: string;
execute_config: ExecuteConfig | null;
context_filter: SessionContextFilter | null;
context: SessionContextFilter | null;
};

export type DeletedSessionInfo = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import { useThirdwebClient } from "@/constants/thirdweb.client";
import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
import { ArrowRightIcon } from "lucide-react";
import Link from "next/link";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { useActiveAccount, useActiveWalletChain } from "thirdweb/react";
import { type ContextFilters, promptNebula } from "../api/chat";
import { type NebulaContext, promptNebula } from "../api/chat";
import { createSession, updateSession } from "../api/session";
import type { ExecuteConfig, SessionInfo } from "../api/types";
import type { SessionInfo } from "../api/types";
import { newChatPageUrlStore, newSessionsStore } from "../stores";
import { ChatBar } from "./ChatBar";
import { type ChatMessage, Chats } from "./Chats";
Expand Down Expand Up @@ -81,39 +81,43 @@ export function ChatPageContent(props: {
useState(false);

const [contextFilters, _setContextFilters] = useState<
ContextFilters | undefined
NebulaContext | undefined
>(() => {
const contextFilterRes = props.session?.context_filter;
const value: ContextFilters = {
chainIds: contextFilterRes?.chain_ids || undefined,
contractAddresses: contextFilterRes?.contract_addresses || undefined,
walletAddresses: contextFilterRes?.wallet_addresses || undefined,
const contextRes = props.session?.context;
const value: NebulaContext = {
chainIds: contextRes?.chain_ids || null,
walletAddress: contextRes?.wallet_address || null,
};

return value;
});

const setContextFilters = useCallback((v: ContextFilters | undefined) => {
const setContextFilters = useCallback((v: NebulaContext | undefined) => {
_setContextFilters(v);
setHasUserUpdatedContextFilters(true);
}, []);

const isNewSession = !props.session;

// if this is a new session, user has not manually updated context filters
// update the context filters to the current user's wallet address and chain id
// if this is a new session, user has not manually updated context
// update the context to the current user's wallet address and chain id
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
if (!isNewSession || hasUserUpdatedContextFilters) {
return;
}

_setContextFilters((_contextFilters) => {
const updatedContextFilters: ContextFilters = _contextFilters
? { ..._contextFilters }
: {};
const updatedContextFilters: NebulaContext = _contextFilters
? {
..._contextFilters,
}
: {
chainIds: [],
walletAddress: null,
};

updatedContextFilters.walletAddresses = address ? [address] : [];
updatedContextFilters.walletAddress = address || null;
updatedContextFilters.chainIds = activeChain
? [activeChain.id.toString()]
: [];
Expand All @@ -122,15 +126,6 @@ export function ChatPageContent(props: {
});
}, [address, isNewSession, hasUserUpdatedContextFilters, activeChain]);

const config: ExecuteConfig | null = useMemo(() => {
return address
? {
mode: "client",
signer_wallet_address: address,
}
: null;
}, [address]);

const [sessionId, _setSessionId] = useState<string | undefined>(
props.session?.id,
);
Expand Down Expand Up @@ -163,12 +158,11 @@ export function ChatPageContent(props: {
const initSession = useCallback(async () => {
const session = await createSession({
authToken: props.authToken,
config,
contextFilters,
context: contextFilters,
});
setSessionId(session.id);
return session;
}, [config, contextFilters, props.authToken, setSessionId]);
}, [contextFilters, props.authToken, setSessionId]);

const handleSendMessage = useCallback(
async (message: string) => {
Expand Down Expand Up @@ -221,7 +215,6 @@ export function ChatPageContent(props: {
abortController,
message: message,
sessionId: currentSessionId,
config: config,
authToken: props.authToken,
handleStream(res) {
if (abortController.signal.aborted) {
Expand Down Expand Up @@ -308,7 +301,7 @@ export function ChatPageContent(props: {
}
}
},
contextFilters: contextFilters,
context: contextFilters,
});
} catch (error) {
if (abortController.signal.aborted) {
Expand Down Expand Up @@ -338,7 +331,6 @@ export function ChatPageContent(props: {
[
sessionId,
contextFilters,
config,
props.authToken,
messages.length,
initSession,
Expand All @@ -363,13 +355,12 @@ export function ChatPageContent(props: {
const showEmptyState = !userHasSubmittedMessage && messages.length === 0;

const handleUpdateContextFilters = async (
values: ContextFilters | undefined,
values: NebulaContext | undefined,
) => {
// if session is not yet created, don't need to update sessions - starting a chat will create a session with the context filters
// if session is not yet created, don't need to update sessions - starting a chat will create a session with the context
if (sessionId) {
await updateSession({
authToken: props.authToken,
config,
sessionId,
contextFilters: values,
});
Expand Down
Loading
Loading