@nastechai/agent 0.16.0 → 0.17.0
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/eslint.config.js +23 -0
- package/index.html +24 -0
- package/package.json +54 -26
- package/package.json.bak +89 -0
- package/package.json.pub +88 -0
- package/src/App.tsx +1173 -0
- package/src/components/AuthWidget.tsx +150 -0
- package/src/components/AutoField.tsx +206 -0
- package/src/components/Backdrop.tsx +93 -0
- package/src/components/ChatSidebar.tsx +394 -0
- package/src/components/DeleteConfirmDialog.tsx +40 -0
- package/src/components/LanguageSwitcher.tsx +186 -0
- package/src/components/Markdown.tsx +383 -0
- package/src/components/ModelInfoCard.tsx +112 -0
- package/src/components/ModelPickerDialog.tsx +470 -0
- package/src/components/OAuthLoginModal.tsx +374 -0
- package/src/components/OAuthProvidersCard.tsx +287 -0
- package/src/components/PlatformsCard.tsx +97 -0
- package/src/components/ScheduleBuilder.tsx +273 -0
- package/src/components/SidebarFooter.tsx +42 -0
- package/src/components/SidebarStatusStrip.tsx +72 -0
- package/src/components/SlashPopover.tsx +171 -0
- package/src/components/ThemeSwitcher.tsx +243 -0
- package/src/components/ToolCall.tsx +228 -0
- package/src/components/ToolsetConfigDrawer.tsx +448 -0
- package/src/contexts/PageHeaderProvider.tsx +139 -0
- package/src/contexts/SystemActions.tsx +120 -0
- package/src/contexts/page-header-context.ts +12 -0
- package/src/contexts/system-actions-context.ts +18 -0
- package/src/contexts/usePageHeader.ts +10 -0
- package/src/contexts/useSystemActions.ts +15 -0
- package/src/hooks/useModalBehavior.ts +44 -0
- package/src/hooks/useSidebarStatus.ts +27 -0
- package/src/i18n/af.ts +702 -0
- package/src/i18n/context.tsx +123 -0
- package/src/i18n/de.ts +701 -0
- package/src/i18n/en.ts +708 -0
- package/src/i18n/es.ts +701 -0
- package/src/i18n/fr.ts +701 -0
- package/src/i18n/ga.ts +702 -0
- package/src/i18n/hu.ts +702 -0
- package/src/i18n/index.ts +2 -0
- package/src/i18n/it.ts +701 -0
- package/src/i18n/ja.ts +702 -0
- package/src/i18n/ko.ts +702 -0
- package/src/i18n/pt.ts +702 -0
- package/src/i18n/ru.ts +702 -0
- package/src/i18n/tr.ts +702 -0
- package/src/i18n/types.ts +710 -0
- package/src/i18n/uk.ts +702 -0
- package/src/i18n/zh-hant.ts +702 -0
- package/src/i18n/zh.ts +698 -0
- package/src/index.css +274 -0
- package/src/lib/api.ts +1585 -0
- package/src/lib/dashboard-flags.ts +15 -0
- package/src/lib/format.ts +9 -0
- package/src/lib/fuzzy.ts +192 -0
- package/src/lib/gatewayClient.ts +253 -0
- package/src/lib/nested.ts +23 -0
- package/src/lib/resolve-page-title.ts +41 -0
- package/src/lib/schedule.ts +382 -0
- package/src/lib/slashExec.ts +163 -0
- package/src/lib/utils.ts +35 -0
- package/src/main.tsx +25 -0
- package/src/pages/AnalyticsPage.tsx +601 -0
- package/src/pages/ChannelsPage.tsx +772 -0
- package/src/pages/ChatPage.tsx +889 -0
- package/src/pages/ConfigPage.tsx +660 -0
- package/src/pages/CronPage.tsx +524 -0
- package/src/pages/DocsPage.tsx +69 -0
- package/src/pages/EnvPage.tsx +918 -0
- package/src/pages/LogsPage.tsx +246 -0
- package/src/pages/McpPage.tsx +757 -0
- package/src/pages/ModelsPage.tsx +994 -0
- package/src/pages/PairingPage.tsx +276 -0
- package/src/pages/PluginsPage.tsx +580 -0
- package/src/pages/ProfilesPage.tsx +559 -0
- package/src/pages/SessionsPage.tsx +936 -0
- package/src/pages/SkillsPage.tsx +557 -0
- package/src/pages/SystemPage.tsx +1259 -0
- package/src/pages/WebhooksPage.tsx +483 -0
- package/src/plugins/PluginPage.tsx +64 -0
- package/src/plugins/index.ts +6 -0
- package/src/plugins/registry.ts +151 -0
- package/src/plugins/sdk.d.ts +160 -0
- package/src/plugins/slots.ts +199 -0
- package/src/plugins/types.ts +37 -0
- package/src/plugins/usePlugins.ts +133 -0
- package/src/themes/context.tsx +443 -0
- package/src/themes/fonts.ts +160 -0
- package/src/themes/index.ts +3 -0
- package/src/themes/presets.ts +477 -0
- package/src/themes/types.ts +187 -0
- package/tsconfig.app.json +34 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +124 -0
- package/vite.config.ts.timestamp-1780999102396-af6b77b30ebd8.mjs +105 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { api } from "@/lib/api";
|
|
3
|
+
import type { ActionStatusResponse } from "@/lib/api";
|
|
4
|
+
import { Toast } from "@nastechai/ui/ui/components/toast";
|
|
5
|
+
import { useI18n } from "@/i18n";
|
|
6
|
+
import {
|
|
7
|
+
SystemActionsContext,
|
|
8
|
+
type SystemAction,
|
|
9
|
+
} from "./system-actions-context";
|
|
10
|
+
|
|
11
|
+
const ACTION_NAMES: Record<SystemAction, string> = {
|
|
12
|
+
restart: "gateway-restart",
|
|
13
|
+
update: "nastech-update",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function SystemActionsProvider({
|
|
17
|
+
children,
|
|
18
|
+
}: {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
}) {
|
|
21
|
+
const [pendingAction, setPendingAction] = useState<SystemAction | null>(null);
|
|
22
|
+
const [activeAction, setActiveAction] = useState<SystemAction | null>(null);
|
|
23
|
+
const [actionStatus, setActionStatus] = useState<ActionStatusResponse | null>(
|
|
24
|
+
null,
|
|
25
|
+
);
|
|
26
|
+
const [toast, setToast] = useState<ToastState | null>(null);
|
|
27
|
+
const { t } = useI18n();
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!toast) return;
|
|
31
|
+
const timer = setTimeout(() => setToast(null), 4000);
|
|
32
|
+
return () => clearTimeout(timer);
|
|
33
|
+
}, [toast]);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!activeAction) return;
|
|
37
|
+
const name = ACTION_NAMES[activeAction];
|
|
38
|
+
let cancelled = false;
|
|
39
|
+
|
|
40
|
+
const poll = async () => {
|
|
41
|
+
try {
|
|
42
|
+
const resp = await api.getActionStatus(name);
|
|
43
|
+
if (cancelled) return;
|
|
44
|
+
setActionStatus(resp);
|
|
45
|
+
if (!resp.running) {
|
|
46
|
+
const ok = resp.exit_code === 0;
|
|
47
|
+
setToast({
|
|
48
|
+
type: ok ? "success" : "error",
|
|
49
|
+
message: ok
|
|
50
|
+
? t.status.actionFinished
|
|
51
|
+
: `${t.status.actionFailed} (exit ${resp.exit_code ?? "?"})`,
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
} catch {
|
|
56
|
+
// transient fetch error; keep polling
|
|
57
|
+
}
|
|
58
|
+
if (!cancelled) setTimeout(poll, 1500);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
poll();
|
|
62
|
+
return () => {
|
|
63
|
+
cancelled = true;
|
|
64
|
+
};
|
|
65
|
+
}, [activeAction, t.status.actionFinished, t.status.actionFailed]);
|
|
66
|
+
|
|
67
|
+
const runAction = useCallback(
|
|
68
|
+
async (action: SystemAction) => {
|
|
69
|
+
setPendingAction(action);
|
|
70
|
+
setActionStatus(null);
|
|
71
|
+
try {
|
|
72
|
+
if (action === "restart") {
|
|
73
|
+
await api.restartGateway();
|
|
74
|
+
} else {
|
|
75
|
+
await api.updateNasTech();
|
|
76
|
+
}
|
|
77
|
+
setActiveAction(action);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
80
|
+
setToast({
|
|
81
|
+
type: "error",
|
|
82
|
+
message: `${t.status.actionFailed}: ${detail}`,
|
|
83
|
+
});
|
|
84
|
+
} finally {
|
|
85
|
+
setPendingAction(null);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
[t.status.actionFailed],
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const dismissLog = useCallback(() => {
|
|
92
|
+
setActiveAction(null);
|
|
93
|
+
setActionStatus(null);
|
|
94
|
+
}, []);
|
|
95
|
+
|
|
96
|
+
const isRunning = activeAction !== null && actionStatus?.running !== false;
|
|
97
|
+
const isBusy = pendingAction !== null || isRunning;
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<SystemActionsContext.Provider
|
|
101
|
+
value={{
|
|
102
|
+
actionStatus,
|
|
103
|
+
activeAction,
|
|
104
|
+
dismissLog,
|
|
105
|
+
isBusy,
|
|
106
|
+
isRunning,
|
|
107
|
+
pendingAction,
|
|
108
|
+
runAction,
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
{children}
|
|
112
|
+
<Toast toast={toast} />
|
|
113
|
+
</SystemActionsContext.Provider>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface ToastState {
|
|
118
|
+
message: string;
|
|
119
|
+
type: "success" | "error";
|
|
120
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
export interface PageHeaderContextValue {
|
|
5
|
+
setAfterTitle: (node: ReactNode) => void;
|
|
6
|
+
setEnd: (node: ReactNode) => void;
|
|
7
|
+
setTitle: (title: string | null) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const PageHeaderContext = createContext<PageHeaderContextValue | null>(
|
|
11
|
+
null,
|
|
12
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
import type { ActionStatusResponse } from "@/lib/api";
|
|
3
|
+
|
|
4
|
+
export const SystemActionsContext = createContext<SystemActionsState | null>(
|
|
5
|
+
null,
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
export type SystemAction = "restart" | "update";
|
|
9
|
+
|
|
10
|
+
export interface SystemActionsState {
|
|
11
|
+
actionStatus: ActionStatusResponse | null;
|
|
12
|
+
activeAction: SystemAction | null;
|
|
13
|
+
dismissLog: () => void;
|
|
14
|
+
isBusy: boolean;
|
|
15
|
+
isRunning: boolean;
|
|
16
|
+
pendingAction: SystemAction | null;
|
|
17
|
+
runAction: (action: SystemAction) => Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { PageHeaderContext, type PageHeaderContextValue } from "./page-header-context";
|
|
3
|
+
|
|
4
|
+
export function usePageHeader(): PageHeaderContextValue {
|
|
5
|
+
const ctx = useContext(PageHeaderContext);
|
|
6
|
+
if (!ctx) {
|
|
7
|
+
throw new Error("usePageHeader must be used within a PageHeaderProvider");
|
|
8
|
+
}
|
|
9
|
+
return ctx;
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import {
|
|
3
|
+
SystemActionsContext,
|
|
4
|
+
type SystemActionsState,
|
|
5
|
+
} from "./system-actions-context";
|
|
6
|
+
|
|
7
|
+
export function useSystemActions(): SystemActionsState {
|
|
8
|
+
const ctx = useContext(SystemActionsContext);
|
|
9
|
+
if (!ctx) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
"useSystemActions must be used within a SystemActionsProvider",
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return ctx;
|
|
15
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook that adds standard modal behaviors when `open` is true:
|
|
5
|
+
* - Escape key calls `onClose`
|
|
6
|
+
* - Body scroll is locked
|
|
7
|
+
* - Focus is restored to the previously focused element on close
|
|
8
|
+
*
|
|
9
|
+
* Returns a ref to attach to the modal container (for optional future focus trapping).
|
|
10
|
+
*/
|
|
11
|
+
export function useModalBehavior({
|
|
12
|
+
open,
|
|
13
|
+
onClose,
|
|
14
|
+
}: {
|
|
15
|
+
open: boolean;
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
}) {
|
|
18
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!open) return;
|
|
22
|
+
|
|
23
|
+
const prevActive = document.activeElement as HTMLElement | null;
|
|
24
|
+
|
|
25
|
+
const onKey = (e: KeyboardEvent) => {
|
|
26
|
+
if (e.key === "Escape") {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
onClose();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
document.addEventListener("keydown", onKey);
|
|
33
|
+
const prevOverflow = document.body.style.overflow;
|
|
34
|
+
document.body.style.overflow = "hidden";
|
|
35
|
+
|
|
36
|
+
return () => {
|
|
37
|
+
document.removeEventListener("keydown", onKey);
|
|
38
|
+
document.body.style.overflow = prevOverflow;
|
|
39
|
+
prevActive?.focus?.();
|
|
40
|
+
};
|
|
41
|
+
}, [open, onClose]);
|
|
42
|
+
|
|
43
|
+
return containerRef;
|
|
44
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { api } from "@/lib/api";
|
|
3
|
+
import type { StatusResponse } from "@/lib/api";
|
|
4
|
+
|
|
5
|
+
const POLL_MS = 10_000;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Light-weight status poll for the app shell (sidebar). The Status page uses
|
|
9
|
+
* its own faster interval; we keep this slower to avoid duplicate load.
|
|
10
|
+
*/
|
|
11
|
+
export function useSidebarStatus() {
|
|
12
|
+
const [status, setStatus] = useState<StatusResponse | null>(null);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const load = () => {
|
|
16
|
+
api
|
|
17
|
+
.getStatus()
|
|
18
|
+
.then(setStatus)
|
|
19
|
+
.catch(() => {});
|
|
20
|
+
};
|
|
21
|
+
load();
|
|
22
|
+
const id = setInterval(load, POLL_MS);
|
|
23
|
+
return () => clearInterval(id);
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
return status;
|
|
27
|
+
}
|