Initial commit from agent-native create

This commit is contained in:
agent-native
2026-07-25 17:10:38 +00:00
commit ffea2aeff7
120 changed files with 6804 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
import {
AgentChatSurface,
markAgentChatHomeHandoff,
} from "@agent-native/core/client/agent-chat";
import { useT } from "@agent-native/core/client/i18n";
import { useEffect } from "react";
import { useNavigate, useParams } from "react-router";
import { APP_TITLE } from "@/lib/app-config";
import { TAB_ID } from "@/lib/tab-id";
const SEO_TITLE = `${APP_TITLE} - Open Source AI app starter with actions`;
const SEO_DESCRIPTION =
"Open Source starter for agent-native apps with durable chat, shared actions, UI state, tools, and a backend your agent can extend.";
export function meta() {
return [
{ title: SEO_TITLE },
{
name: "description",
content: SEO_DESCRIPTION,
},
{ property: "og:title", content: SEO_TITLE },
{ property: "og:description", content: SEO_DESCRIPTION },
{ name: "twitter:card", content: "summary" },
{ name: "twitter:title", content: SEO_TITLE },
{ name: "twitter:description", content: SEO_DESCRIPTION },
];
}
function chatThreadPath(threadId: string | null) {
return threadId ? `/chat/${encodeURIComponent(threadId)}` : "/";
}
export default function ChatRoute() {
const { threadId } = useParams();
const navigate = useNavigate();
const t = useT();
const threadUrlSync = threadId
? {
routeThreadId: threadId,
getPath: chatThreadPath,
navigate,
}
: undefined;
useEffect(() => {
function handleChatRunning(event: Event) {
const detail = (event as CustomEvent).detail;
if (detail?.isRunning === true) markAgentChatHomeHandoff("chat");
}
window.addEventListener("agentNative.chatRunning", handleChatRunning);
return () =>
window.removeEventListener("agentNative.chatRunning", handleChatRunning);
}, []);
return (
<div className="flex h-full min-h-0 flex-col bg-background">
<AgentChatSurface
mode="page"
chatViewTransition
className="h-full"
defaultMode="chat"
storageKey="chat"
threadUrlSync={threadUrlSync}
browserTabId={TAB_ID}
showHeader={false}
showTabBar={false}
dynamicSuggestions={false}
suggestions={[
t("chat.suggestionCapabilities"),
t("chat.suggestionCustomize"),
t("chat.suggestionActions"),
]}
emptyStateText={t("chat.emptyState")}
emptyStateDisplay="hidden"
centerComposerWhenEmpty
composerLayoutVariant="hero"
composerPlaceholder={t("chat.composerPlaceholder")}
composerSlot={
<div className="mx-auto mb-5 max-w-xl px-4 text-center">
<h1 className="text-2xl font-semibold tracking-normal text-foreground sm:text-3xl">
{t("chat.heroTitle")}
</h1>
<p className="mt-2 text-sm leading-6 text-muted-foreground">
{t("chat.heroDescription")}
</p>
</div>
}
/>
</div>
);
}
+24
View File
@@ -0,0 +1,24 @@
import {
AgentChatSurface,
AgentTabsPage,
} from "@agent-native/core/client/agent-chat";
import { useT } from "@agent-native/core/client/i18n";
import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
import { resolveAgentPageComponent } from "@/lib/agent-page";
import { APP_TITLE } from "@/lib/app-config";
export function meta() {
return [{ title: `Agent - ${APP_TITLE}` }];
}
export default function AgentRoute() {
const t = useT();
useSetPageTitle(t("settings.agentTitle"));
const AgentPage = resolveAgentPageComponent({
AgentChatSurface,
AgentTabsPage,
});
return <AgentPage appName={APP_TITLE} />;
}
+1
View File
@@ -0,0 +1 @@
export { default, meta } from "./_index";
+17
View File
@@ -0,0 +1,17 @@
import { DbAdminPage } from "@agent-native/core/client/db-admin";
import { useT } from "@agent-native/core/client/i18n";
import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
export function meta() {
return [{ title: "Database" }];
}
export default function DatabasePage() {
const t = useT();
useSetPageTitle(t("pages.databaseTitle"));
return (
<div className="h-full">
<DbAdminPage />
</div>
);
}
+2
View File
@@ -0,0 +1,2 @@
export * from "./extensions.$id";
export { default } from "./extensions.$id";
+11
View File
@@ -0,0 +1,11 @@
import { ExtensionViewerPage } from "@agent-native/core/client/extensions";
import { APP_TITLE } from "@/lib/app-config";
export function meta() {
return [{ title: `Extension — ${APP_TITLE}` }];
}
export default function ExtensionViewerRoute() {
return <ExtensionViewerPage />;
}
+11
View File
@@ -0,0 +1,11 @@
import { Navigate } from "react-router";
import { APP_TITLE } from "@/lib/app-config";
export function meta() {
return [{ title: `Extensions — ${APP_TITLE}` }];
}
export default function ExtensionsRoute() {
return <Navigate to="/settings#extensions" replace />;
}
+5
View File
@@ -0,0 +1,5 @@
import { Outlet } from "react-router";
export default function ExtensionsLayout() {
return <Outlet />;
}
+19
View File
@@ -0,0 +1,19 @@
import { useT } from "@agent-native/core/client/i18n";
import { ObservabilityDashboard } from "@agent-native/core/client/observability";
import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
import enUS from "@/i18n/en-US";
export function meta() {
return [{ title: enUS.pages.observabilityPageTitle }];
}
export default function ObservabilityPage() {
const t = useT();
useSetPageTitle(t("pages.observabilityPageTitle"));
return (
<div className="p-6">
<ObservabilityDashboard />
</div>
);
}
+89
View File
@@ -0,0 +1,89 @@
import { ChangelogSettingsCard } from "@agent-native/core/client/changelog";
import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
import { TeamPage } from "@agent-native/core/client/org";
import {
AccountSettingsCard,
SettingsTabsPage,
useAgentSettingsTabs,
type SettingsSearchEntry,
} from "@agent-native/core/client/settings";
import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
import { useMemo } from "react";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { APP_TITLE } from "@/lib/app-config";
import changelog from "../../CHANGELOG.md?raw";
export function meta() {
return [{ title: `Settings - ${APP_TITLE}` }];
}
export default function SettingsRoute() {
const t = useT();
const agentSettingsTabs = useAgentSettingsTabs();
useSetPageTitle(t("settings.title"));
const generalSearchEntries = useMemo<SettingsSearchEntry[]>(
() => [
{
id: "chat-language",
label: t("settings.languageTitle"),
keywords: "language locale translation i18n",
hash: "language",
},
],
[t],
);
return (
<SettingsTabsPage
account={<AccountSettingsCard />}
teamLabel={t("navigation.team")}
extraTabs={agentSettingsTabs}
generalSearchEntries={generalSearchEntries}
general={
<div className="mx-auto w-full max-w-2xl space-y-6">
<p className="text-sm leading-6 text-muted-foreground">
{t("settings.description")}
</p>
<Card id="language" className="scroll-mt-16">
<CardHeader>
<CardTitle className="text-base">
{t("settings.languageTitle")}
</CardTitle>
<CardDescription>
{t("settings.languageDescription")}
</CardDescription>
</CardHeader>
<CardContent className="max-w-xs space-y-1.5">
<Label>{t("settings.languageLabel")}</Label>
<LanguagePicker label={t("settings.languageLabel")} />
</CardContent>
</Card>
</div>
}
team={
<div className="mx-auto w-full max-w-3xl">
<TeamPage
showTitle={false}
createOrgDescription={t("pages.teamCreateOrgDescription")}
/>
</div>
}
whatsNew={
<div className="mx-auto w-full max-w-2xl">
<ChangelogSettingsCard markdown={changelog} />
</div>
}
/>
);
}
+11
View File
@@ -0,0 +1,11 @@
import { Navigate } from "react-router";
import { APP_TITLE } from "@/lib/app-config";
export function meta() {
return [{ title: `Team — ${APP_TITLE}` }];
}
export default function TeamRoute() {
return <Navigate to="/settings#organization" replace />;
}