@ghostchain1/ghostcopilot-react 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +20 -2
- package/dist/ChatWidget.d.ts +16 -0
- package/dist/ChatWidget.js +100 -0
- package/dist/GhostCopilot.d.ts +21 -0
- package/dist/GhostCopilot.js +62 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/useGhostCopilot.d.ts +28 -0
- package/dist/useGhostCopilot.js +107 -0
- package/package.json +47 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GhostChain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @ghostchain1/ghostcopilot-react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
GhostCopilot React — Floating AI chat widget for GhostCloud apps
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @ghostchain1/ghostcopilot-react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { /* see exports */ } from "@ghostchain1/ghostcopilot-react";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Part of the [GhostOS](https://github.com/ghostmode25/GhostOS) monorepo.
|
|
18
|
+
|
|
19
|
+
## License
|
|
20
|
+
|
|
21
|
+
MIT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GhostCopilot — Chat Widget UI Component
|
|
3
|
+
*
|
|
4
|
+
* Renders the floating chat interface: message thread + input.
|
|
5
|
+
* Designed to be embedded in a floating panel by GhostCopilot.tsx.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChatMessage } from "./useGhostCopilot.js";
|
|
8
|
+
interface ChatWidgetProps {
|
|
9
|
+
messages: ChatMessage[];
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
error: string | null;
|
|
12
|
+
onSend: (content: string) => void;
|
|
13
|
+
onClear: () => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function ChatWidget({ messages, isLoading, error, onSend, onClear }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GhostCopilot — Chat Widget UI Component
|
|
3
|
+
*
|
|
4
|
+
* Renders the floating chat interface: message thread + input.
|
|
5
|
+
* Designed to be embedded in a floating panel by GhostCopilot.tsx.
|
|
6
|
+
*/
|
|
7
|
+
"use client";
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
import React, { useRef, useEffect } from "react";
|
|
10
|
+
export function ChatWidget({ messages, isLoading, error, onSend, onClear }) {
|
|
11
|
+
const [input, setInput] = React.useState("");
|
|
12
|
+
const bottomRef = useRef(null);
|
|
13
|
+
const inputRef = useRef(null);
|
|
14
|
+
// Auto-scroll to bottom on new messages
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
17
|
+
}, [messages]);
|
|
18
|
+
const handleSubmit = (e) => {
|
|
19
|
+
e.preventDefault();
|
|
20
|
+
const text = input.trim();
|
|
21
|
+
if (!text || isLoading)
|
|
22
|
+
return;
|
|
23
|
+
setInput("");
|
|
24
|
+
onSend(text);
|
|
25
|
+
};
|
|
26
|
+
return (_jsxs("div", { style: {
|
|
27
|
+
display: "flex",
|
|
28
|
+
flexDirection: "column",
|
|
29
|
+
height: "100%",
|
|
30
|
+
fontFamily: "system-ui, sans-serif",
|
|
31
|
+
fontSize: "14px",
|
|
32
|
+
}, children: [_jsxs("div", { style: {
|
|
33
|
+
display: "flex",
|
|
34
|
+
alignItems: "center",
|
|
35
|
+
justifyContent: "space-between",
|
|
36
|
+
padding: "10px 14px",
|
|
37
|
+
background: "linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)",
|
|
38
|
+
color: "#fff",
|
|
39
|
+
borderRadius: "12px 12px 0 0",
|
|
40
|
+
fontWeight: 600,
|
|
41
|
+
}, children: [_jsx("span", { children: "\u26A1 GhostCopilot" }), _jsx("button", { onClick: onClear, title: "Clear chat", style: {
|
|
42
|
+
background: "transparent",
|
|
43
|
+
border: "none",
|
|
44
|
+
color: "rgba(255,255,255,0.8)",
|
|
45
|
+
cursor: "pointer",
|
|
46
|
+
fontSize: "18px",
|
|
47
|
+
lineHeight: 1,
|
|
48
|
+
padding: "2px 4px",
|
|
49
|
+
}, "aria-label": "Clear chat", children: "\u00D7" })] }), _jsxs("div", { style: {
|
|
50
|
+
flex: 1,
|
|
51
|
+
overflowY: "auto",
|
|
52
|
+
padding: "12px",
|
|
53
|
+
background: "#0f0f13",
|
|
54
|
+
display: "flex",
|
|
55
|
+
flexDirection: "column",
|
|
56
|
+
gap: "8px",
|
|
57
|
+
}, children: [messages.length === 0 && !isLoading && (_jsxs("div", { style: { color: "#6b7280", textAlign: "center", marginTop: "40px" }, children: ["Ask me anything about GhostChain!", _jsx("br", {}), _jsx("small", { style: { opacity: 0.6 }, children: "swap, bridge, governance, analytics\u2026" })] })), messages.map((msg) => (_jsx(MessageBubble, { message: msg }, msg.id))), isLoading && messages[messages.length - 1]?.content === "" && (_jsx("div", { style: { color: "#6b7280", fontStyle: "italic" }, children: "GhostCopilot is thinking\u2026" })), error && _jsx("div", { style: { color: "#f87171", fontSize: "12px" }, children: error }), _jsx("div", { ref: bottomRef })] }), _jsxs("form", { onSubmit: handleSubmit, style: {
|
|
58
|
+
display: "flex",
|
|
59
|
+
gap: "8px",
|
|
60
|
+
padding: "10px",
|
|
61
|
+
background: "#1a1a2e",
|
|
62
|
+
borderRadius: "0 0 12px 12px",
|
|
63
|
+
borderTop: "1px solid #2d2d44",
|
|
64
|
+
}, children: [_jsx("input", { ref: inputRef, type: "text", value: input, onChange: (e) => setInput(e.target.value), placeholder: "Ask GhostCopilot\u2026", disabled: isLoading, style: {
|
|
65
|
+
flex: 1,
|
|
66
|
+
background: "#0f0f1a",
|
|
67
|
+
border: "1px solid #3d3d5c",
|
|
68
|
+
borderRadius: "8px",
|
|
69
|
+
padding: "8px 12px",
|
|
70
|
+
color: "#e0e0ff",
|
|
71
|
+
outline: "none",
|
|
72
|
+
fontSize: "13px",
|
|
73
|
+
}, "aria-label": "Chat input" }), _jsx("button", { type: "submit", disabled: isLoading || !input.trim(), style: {
|
|
74
|
+
background: isLoading ? "#4b5563" : "#6366f1",
|
|
75
|
+
border: "none",
|
|
76
|
+
borderRadius: "8px",
|
|
77
|
+
padding: "8px 14px",
|
|
78
|
+
color: "#fff",
|
|
79
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
80
|
+
fontWeight: 600,
|
|
81
|
+
fontSize: "13px",
|
|
82
|
+
transition: "background 0.2s",
|
|
83
|
+
}, "aria-label": "Send message", children: isLoading ? "…" : "Send" })] })] }));
|
|
84
|
+
}
|
|
85
|
+
function MessageBubble({ message }) {
|
|
86
|
+
const isUser = message.role === "user";
|
|
87
|
+
return (_jsx("div", { style: {
|
|
88
|
+
display: "flex",
|
|
89
|
+
justifyContent: isUser ? "flex-end" : "flex-start",
|
|
90
|
+
}, children: _jsx("div", { style: {
|
|
91
|
+
maxWidth: "85%",
|
|
92
|
+
padding: "8px 12px",
|
|
93
|
+
borderRadius: isUser ? "12px 12px 2px 12px" : "12px 12px 12px 2px",
|
|
94
|
+
background: isUser ? "#4f46e5" : "#1e1e2e",
|
|
95
|
+
color: isUser ? "#fff" : "#c9d1d9",
|
|
96
|
+
whiteSpace: "pre-wrap",
|
|
97
|
+
wordBreak: "break-word",
|
|
98
|
+
lineHeight: 1.5,
|
|
99
|
+
}, children: message.content || _jsx("span", { style: { opacity: 0.4 }, children: "\u258C" }) }) }));
|
|
100
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GhostCopilot — Floating Widget Shell Component
|
|
3
|
+
*
|
|
4
|
+
* Renders a floating action button (FAB) in the bottom-right corner.
|
|
5
|
+
* Clicking expands a chat panel. All state managed via useGhostCopilot hook.
|
|
6
|
+
*/
|
|
7
|
+
export interface GhostCopilotProps {
|
|
8
|
+
/** GhostCopilot service URL. Defaults to process.env.NEXT_PUBLIC_GHOSTCOPILOT_URL */
|
|
9
|
+
serviceUrl?: string;
|
|
10
|
+
/** Connected wallet address (optional, for personalised context) */
|
|
11
|
+
walletAddress?: string;
|
|
12
|
+
/** Chain ID context. Defaults to 14000301 */
|
|
13
|
+
chainId?: number;
|
|
14
|
+
/** Width of the chat panel in pixels. Default 380 */
|
|
15
|
+
panelWidth?: number;
|
|
16
|
+
/** Height of the chat panel in pixels. Default 520 */
|
|
17
|
+
panelHeight?: number;
|
|
18
|
+
/** CSS z-index for the widget. Default 9999 */
|
|
19
|
+
zIndex?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function GhostCopilot({ serviceUrl, walletAddress, chainId, panelWidth, panelHeight, zIndex, }: GhostCopilotProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GhostCopilot — Floating Widget Shell Component
|
|
3
|
+
*
|
|
4
|
+
* Renders a floating action button (FAB) in the bottom-right corner.
|
|
5
|
+
* Clicking expands a chat panel. All state managed via useGhostCopilot hook.
|
|
6
|
+
*/
|
|
7
|
+
"use client";
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
import React, { useState } from "react";
|
|
10
|
+
import { useGhostCopilot } from "./useGhostCopilot.js";
|
|
11
|
+
import { ChatWidget } from "./ChatWidget.js";
|
|
12
|
+
export function GhostCopilot({ serviceUrl, walletAddress, chainId, panelWidth = 380, panelHeight = 520, zIndex = 9999, }) {
|
|
13
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
14
|
+
const { messages, isLoading, error, sendMessage, clearMessages } = useGhostCopilot({
|
|
15
|
+
serviceUrl,
|
|
16
|
+
walletAddress,
|
|
17
|
+
chainId,
|
|
18
|
+
});
|
|
19
|
+
const handleClear = () => {
|
|
20
|
+
clearMessages();
|
|
21
|
+
setIsOpen(false);
|
|
22
|
+
};
|
|
23
|
+
return (_jsxs("div", { style: {
|
|
24
|
+
position: "fixed",
|
|
25
|
+
bottom: "24px",
|
|
26
|
+
right: "24px",
|
|
27
|
+
zIndex,
|
|
28
|
+
display: "flex",
|
|
29
|
+
flexDirection: "column",
|
|
30
|
+
alignItems: "flex-end",
|
|
31
|
+
gap: "12px",
|
|
32
|
+
}, children: [isOpen && (_jsx("div", { style: {
|
|
33
|
+
width: `${panelWidth}px`,
|
|
34
|
+
height: `${panelHeight}px`,
|
|
35
|
+
background: "#0f0f13",
|
|
36
|
+
borderRadius: "12px",
|
|
37
|
+
boxShadow: "0 20px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(99,102,241,0.3)",
|
|
38
|
+
overflow: "hidden",
|
|
39
|
+
display: "flex",
|
|
40
|
+
flexDirection: "column",
|
|
41
|
+
animation: "ghostcopilot-slide-up 0.2s ease-out",
|
|
42
|
+
}, children: _jsx(ChatWidget, { messages: messages, isLoading: isLoading, error: error, onSend: sendMessage, onClear: handleClear }) })), _jsx("button", { onClick: () => setIsOpen((v) => !v), "aria-label": isOpen ? "Close GhostCopilot" : "Open GhostCopilot", style: {
|
|
43
|
+
width: "56px",
|
|
44
|
+
height: "56px",
|
|
45
|
+
borderRadius: "50%",
|
|
46
|
+
background: "linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)",
|
|
47
|
+
border: "none",
|
|
48
|
+
cursor: "pointer",
|
|
49
|
+
display: "flex",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
justifyContent: "center",
|
|
52
|
+
boxShadow: "0 4px 20px rgba(99,102,241,0.5)",
|
|
53
|
+
fontSize: "24px",
|
|
54
|
+
transition: "transform 0.2s, box-shadow 0.2s",
|
|
55
|
+
transform: isOpen ? "rotate(45deg)" : "none",
|
|
56
|
+
}, title: isOpen ? "Close GhostCopilot" : "Chat with GhostCopilot AI", children: isOpen ? "✕" : "⚡" }), _jsx("style", { children: `
|
|
57
|
+
@keyframes ghostcopilot-slide-up {
|
|
58
|
+
from { opacity: 0; transform: translateY(20px) scale(0.96); }
|
|
59
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
60
|
+
}
|
|
61
|
+
` })] }));
|
|
62
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useGhostCopilot — React hook for GhostCopilot SSE streaming
|
|
3
|
+
*
|
|
4
|
+
* Manages chat state, sends messages, and reads SSE chunks.
|
|
5
|
+
*/
|
|
6
|
+
export interface ChatMessage {
|
|
7
|
+
id: string;
|
|
8
|
+
role: "user" | "assistant";
|
|
9
|
+
content: string;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
}
|
|
12
|
+
interface UseGhostCopilotOptions {
|
|
13
|
+
/** Base URL of the GhostCopilot service. Defaults to NEXT_PUBLIC_GHOSTCOPILOT_URL env var */
|
|
14
|
+
serviceUrl?: string;
|
|
15
|
+
/** Optional connected wallet address for personalised context */
|
|
16
|
+
walletAddress?: string;
|
|
17
|
+
/** Chain ID for context. Defaults to 14000301 (L1) */
|
|
18
|
+
chainId?: number;
|
|
19
|
+
}
|
|
20
|
+
interface UseGhostCopilotReturn {
|
|
21
|
+
messages: ChatMessage[];
|
|
22
|
+
isLoading: boolean;
|
|
23
|
+
error: string | null;
|
|
24
|
+
sendMessage: (content: string) => Promise<void>;
|
|
25
|
+
clearMessages: () => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function useGhostCopilot(options?: UseGhostCopilotOptions): UseGhostCopilotReturn;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useGhostCopilot — React hook for GhostCopilot SSE streaming
|
|
3
|
+
*
|
|
4
|
+
* Manages chat state, sends messages, and reads SSE chunks.
|
|
5
|
+
*/
|
|
6
|
+
"use client";
|
|
7
|
+
import { useState, useCallback, useRef } from "react";
|
|
8
|
+
function generateId() {
|
|
9
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
10
|
+
}
|
|
11
|
+
export function useGhostCopilot(options = {}) {
|
|
12
|
+
const serviceUrl = options.serviceUrl ??
|
|
13
|
+
(typeof process !== "undefined" ? process.env["NEXT_PUBLIC_GHOSTCOPILOT_URL"] : undefined) ??
|
|
14
|
+
"http://localhost:9200";
|
|
15
|
+
const [messages, setMessages] = useState([]);
|
|
16
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
17
|
+
const [error, setError] = useState(null);
|
|
18
|
+
const abortRef = useRef(null);
|
|
19
|
+
const sendMessage = useCallback(async (content) => {
|
|
20
|
+
if (!content.trim())
|
|
21
|
+
return;
|
|
22
|
+
// Cancel any in-flight request
|
|
23
|
+
abortRef.current?.abort();
|
|
24
|
+
abortRef.current = new AbortController();
|
|
25
|
+
const userMsg = {
|
|
26
|
+
id: generateId(),
|
|
27
|
+
role: "user",
|
|
28
|
+
content: content.trim(),
|
|
29
|
+
timestamp: Date.now(),
|
|
30
|
+
};
|
|
31
|
+
setMessages((prev) => [...prev, userMsg]);
|
|
32
|
+
setIsLoading(true);
|
|
33
|
+
setError(null);
|
|
34
|
+
const assistantId = generateId();
|
|
35
|
+
// Optimistically add empty assistant message for streaming
|
|
36
|
+
setMessages((prev) => [
|
|
37
|
+
...prev,
|
|
38
|
+
{ id: assistantId, role: "assistant", content: "", timestamp: Date.now() },
|
|
39
|
+
]);
|
|
40
|
+
try {
|
|
41
|
+
const conversationHistory = [
|
|
42
|
+
...messages.map((m) => ({ role: m.role, content: m.content })),
|
|
43
|
+
{ role: "user", content: content.trim() },
|
|
44
|
+
];
|
|
45
|
+
const res = await fetch(`${serviceUrl}/v1/chat`, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: { "Content-Type": "application/json" },
|
|
48
|
+
body: JSON.stringify({
|
|
49
|
+
messages: conversationHistory,
|
|
50
|
+
walletAddress: options.walletAddress,
|
|
51
|
+
chainId: options.chainId ?? 14000301,
|
|
52
|
+
stream: true,
|
|
53
|
+
}),
|
|
54
|
+
signal: abortRef.current.signal,
|
|
55
|
+
});
|
|
56
|
+
if (!res.ok || !res.body) {
|
|
57
|
+
throw new Error(`HTTP ${res.status}`);
|
|
58
|
+
}
|
|
59
|
+
const reader = res.body.getReader();
|
|
60
|
+
const decoder = new TextDecoder();
|
|
61
|
+
let accumulated = "";
|
|
62
|
+
while (true) {
|
|
63
|
+
const { done, value } = await reader.read();
|
|
64
|
+
if (done)
|
|
65
|
+
break;
|
|
66
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
67
|
+
const lines = chunk.split("\n");
|
|
68
|
+
for (const line of lines) {
|
|
69
|
+
if (!line.startsWith("data: "))
|
|
70
|
+
continue;
|
|
71
|
+
const payload = line.slice(6).trim();
|
|
72
|
+
if (payload === "[DONE]")
|
|
73
|
+
break;
|
|
74
|
+
try {
|
|
75
|
+
const data = JSON.parse(payload);
|
|
76
|
+
if (data.error)
|
|
77
|
+
throw new Error(data.error);
|
|
78
|
+
const delta = data.delta ?? data.content ?? "";
|
|
79
|
+
if (delta) {
|
|
80
|
+
accumulated += delta;
|
|
81
|
+
setMessages((prev) => prev.map((m) => (m.id === assistantId ? { ...m, content: accumulated } : m)));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Non-JSON SSE line — skip
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if (err instanceof Error && err.name === "AbortError")
|
|
92
|
+
return;
|
|
93
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
94
|
+
setError(msg);
|
|
95
|
+
setMessages((prev) => prev.map((m) => (m.id === assistantId ? { ...m, content: `Error: ${msg}` } : m)));
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
setIsLoading(false);
|
|
99
|
+
}
|
|
100
|
+
}, [messages, serviceUrl, options.walletAddress, options.chainId]);
|
|
101
|
+
const clearMessages = useCallback(() => {
|
|
102
|
+
abortRef.current?.abort();
|
|
103
|
+
setMessages([]);
|
|
104
|
+
setError(null);
|
|
105
|
+
}, []);
|
|
106
|
+
return { messages, isLoading, error, sendMessage, clearMessages };
|
|
107
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghostchain1/ghostcopilot-react",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "GhostCopilot React — Floating AI chat widget for GhostCloud apps",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
20
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"typescript": "^5.9.3",
|
|
24
|
+
"vitest": "^3.2.7",
|
|
25
|
+
"@types/react": "^19.0.0",
|
|
26
|
+
"@types/react-dom": "^19.0.0",
|
|
27
|
+
"@types/node": "^22.0.0"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/ghostmode25/GhostOS.git",
|
|
35
|
+
"directory": "packages/ghostcopilot-react"
|
|
36
|
+
},
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"homepage": "https://github.com/ghostmode25/GhostOS/tree/main/packages/ghostcopilot-react#ghostchain1-ghostcopilot-react",
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"registry": "https://registry.npmjs.org/",
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc",
|
|
45
|
+
"dev": "tsc --watch",
|
|
46
|
+
"test": "vitest run --passWithNoTests",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"lint": "eslint src/"
|
|
49
|
+
}
|
|
6
50
|
}
|