@liminalcash/nim-chat 0.1.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/README.md +160 -0
- package/dist/NimChat.d.ts +4 -0
- package/dist/NimChat.d.ts.map +1 -0
- package/dist/components/ChatInput.d.ts +8 -0
- package/dist/components/ChatInput.d.ts.map +1 -0
- package/dist/components/ChatMessage.d.ts +8 -0
- package/dist/components/ChatMessage.d.ts.map +1 -0
- package/dist/components/ChatPanel.d.ts +17 -0
- package/dist/components/ChatPanel.d.ts.map +1 -0
- package/dist/components/ConfirmationCard.d.ts +10 -0
- package/dist/components/ConfirmationCard.d.ts.map +1 -0
- package/dist/components/LoginPanel.d.ts +7 -0
- package/dist/components/LoginPanel.d.ts.map +1 -0
- package/dist/components/ThinkingIndicator.d.ts +2 -0
- package/dist/components/ThinkingIndicator.d.ts.map +1 -0
- package/dist/fonts/abc-marist/ABCMarist-Black.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-BlackItalic.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-Bold.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-BoldItalic.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-Book.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-BookItalic.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-Medium.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-MediumItalic.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-Regular.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-RegularItalic.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-SemiBold.otf +0 -0
- package/dist/fonts/abc-marist/ABCMarist-SemiBoldItalic.otf +0 -0
- package/dist/fonts/helvetica-monospaced-pro/HelveticaMonospacedPro-Bd.otf +0 -0
- package/dist/fonts/helvetica-monospaced-pro/HelveticaMonospacedPro-BdIt.otf +0 -0
- package/dist/fonts/helvetica-monospaced-pro/HelveticaMonospacedPro-It.otf +0 -0
- package/dist/fonts/helvetica-monospaced-pro/HelveticaMonospacedPro-Rg.otf +0 -0
- package/dist/hooks/useNimWebSocket.d.ts +20 -0
- package/dist/hooks/useNimWebSocket.d.ts.map +1 -0
- package/dist/index.cjs +53 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7515 -0
- package/dist/styles/theme.d.ts +90 -0
- package/dist/styles/theme.d.ts.map +1 -0
- package/dist/styles.css +1 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/auth.d.ts +12 -0
- package/dist/utils/auth.d.ts.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# @becomeliminal/nim-chat
|
|
2
|
+
|
|
3
|
+
A React chat widget that connects to any nim SDK backend (Go, Python, etc).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @becomeliminal/nim-chat
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { NimChat } from '@becomeliminal/nim-chat';
|
|
15
|
+
import '@becomeliminal/nim-chat/styles.css';
|
|
16
|
+
|
|
17
|
+
function App() {
|
|
18
|
+
return (
|
|
19
|
+
<NimChat
|
|
20
|
+
wsUrl="ws://localhost:8080/ws"
|
|
21
|
+
title="Nim"
|
|
22
|
+
position="bottom-right"
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Props
|
|
29
|
+
|
|
30
|
+
| Prop | Type | Default | Description |
|
|
31
|
+
|------|------|---------|-------------|
|
|
32
|
+
| `wsUrl` | `string` | **required** | WebSocket URL to connect to |
|
|
33
|
+
| `title` | `string` | `"Nim"` | Header title in the chat panel |
|
|
34
|
+
| `position` | `"bottom-right" \| "bottom-left"` | `"bottom-right"` | Widget position |
|
|
35
|
+
| `defaultOpen` | `boolean` | `false` | Whether the panel starts open |
|
|
36
|
+
|
|
37
|
+
## WebSocket Protocol
|
|
38
|
+
|
|
39
|
+
The widget implements the nim SDK WebSocket protocol:
|
|
40
|
+
|
|
41
|
+
### Client → Server
|
|
42
|
+
|
|
43
|
+
| Type | Fields | Description |
|
|
44
|
+
|------|--------|-------------|
|
|
45
|
+
| `new_conversation` | - | Start a new conversation |
|
|
46
|
+
| `resume_conversation` | `conversationId` | Resume existing conversation |
|
|
47
|
+
| `message` | `content` | Send a user message |
|
|
48
|
+
| `confirm` | `actionId` | Approve a pending action |
|
|
49
|
+
| `cancel` | `actionId` | Cancel a pending action |
|
|
50
|
+
|
|
51
|
+
### Server → Client
|
|
52
|
+
|
|
53
|
+
| Type | Fields | Description |
|
|
54
|
+
|------|--------|-------------|
|
|
55
|
+
| `conversation_started` | `conversationId` | New conversation created |
|
|
56
|
+
| `conversation_resumed` | `conversationId`, `messages[]` | Conversation restored |
|
|
57
|
+
| `text_chunk` | `content` | Streaming text chunk |
|
|
58
|
+
| `text` | `content` | Complete message |
|
|
59
|
+
| `confirm_request` | `actionId`, `tool`, `summary`, `expiresAt` | Action requires approval |
|
|
60
|
+
| `complete` | `tokenUsage?` | Turn completed |
|
|
61
|
+
| `error` | `content` | Error occurred |
|
|
62
|
+
|
|
63
|
+
## Advanced Usage
|
|
64
|
+
|
|
65
|
+
### Custom Implementation
|
|
66
|
+
|
|
67
|
+
You can use individual components and the hook for custom implementations:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import {
|
|
71
|
+
ChatPanel,
|
|
72
|
+
ChatMessage,
|
|
73
|
+
ChatInput,
|
|
74
|
+
ConfirmationCard,
|
|
75
|
+
ThinkingIndicator,
|
|
76
|
+
useNimWebSocket,
|
|
77
|
+
} from '@becomeliminal/nim-chat';
|
|
78
|
+
import '@becomeliminal/nim-chat/styles.css';
|
|
79
|
+
|
|
80
|
+
function CustomChat() {
|
|
81
|
+
const {
|
|
82
|
+
messages,
|
|
83
|
+
isStreaming,
|
|
84
|
+
connectionState,
|
|
85
|
+
confirmationRequest,
|
|
86
|
+
sendMessage,
|
|
87
|
+
confirmAction,
|
|
88
|
+
cancelAction,
|
|
89
|
+
} = useNimWebSocket({
|
|
90
|
+
wsUrl: 'ws://localhost:8080/ws',
|
|
91
|
+
onError: (error) => console.error(error),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Build your own UI...
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Theme Tokens
|
|
99
|
+
|
|
100
|
+
Access design tokens for consistent styling:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { theme, colors, typography, spacing } from '@becomeliminal/nim-chat';
|
|
104
|
+
|
|
105
|
+
// colors.orange = '#FF6D00'
|
|
106
|
+
// colors.cream = '#F1EDE7'
|
|
107
|
+
// etc.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Install dependencies
|
|
114
|
+
npm install
|
|
115
|
+
|
|
116
|
+
# Start dev server with example
|
|
117
|
+
npm run dev
|
|
118
|
+
|
|
119
|
+
# Build for production
|
|
120
|
+
npm run build
|
|
121
|
+
|
|
122
|
+
# Type check
|
|
123
|
+
npm run typecheck
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Testing with nim-go-sdk
|
|
127
|
+
|
|
128
|
+
1. Start the nim-go-sdk example server:
|
|
129
|
+
```bash
|
|
130
|
+
cd /path/to/nim-go-sdk/examples/basic
|
|
131
|
+
ANTHROPIC_API_KEY=your-key go run main.go
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
2. Run the nim-chat example:
|
|
135
|
+
```bash
|
|
136
|
+
cd nim-chat
|
|
137
|
+
npm run dev
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
3. Open http://localhost:5173 and test:
|
|
141
|
+
- Click bubble → panel opens
|
|
142
|
+
- Send message → streaming response
|
|
143
|
+
- Trigger tool → confirmation card appears
|
|
144
|
+
- Approve/cancel → action executes or cancels
|
|
145
|
+
- Refresh → conversation resumes from localStorage
|
|
146
|
+
|
|
147
|
+
## Design System
|
|
148
|
+
|
|
149
|
+
Based on the Liminal mobile app design:
|
|
150
|
+
|
|
151
|
+
- **Orange** `#FF6D00` - Primary, user bubbles, CTAs
|
|
152
|
+
- **Cream** `#F1EDE7` - Background, assistant bubbles
|
|
153
|
+
- **Blue** `#9BC1F3` - Focus states, interactive elements
|
|
154
|
+
- **Black** `#231F18` - Primary text
|
|
155
|
+
- **Brown** `#492610` - Secondary text
|
|
156
|
+
- **Green** `#188A31` - Success, approval
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NimChat.d.ts","sourceRoot":"","sources":["../src/NimChat.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,wBAAgB,OAAO,CAAC,EACtB,KAAK,EACL,MAAmC,EACnC,KAAa,EACb,QAAyB,EACzB,WAAmB,GACpB,EAAE,YAAY,2CAqId"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface ChatInputProps {
|
|
2
|
+
onSend: (message: string) => void;
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function ChatInput({ onSend, disabled, placeholder, }: ChatInputProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=ChatInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../src/components/ChatInput.tsx"],"names":[],"mappings":"AAEA,UAAU,cAAc;IACtB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,QAAgB,EAChB,WAAiC,GAClC,EAAE,cAAc,2CA6EhB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatMessage.d.ts","sourceRoot":"","sources":["../../src/components/ChatMessage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CAmCxD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Message, ConfirmationRequest, ConnectionState } from '../types';
|
|
2
|
+
|
|
3
|
+
interface ChatPanelProps {
|
|
4
|
+
title: string;
|
|
5
|
+
messages: Message[];
|
|
6
|
+
isStreaming: boolean;
|
|
7
|
+
connectionState: ConnectionState;
|
|
8
|
+
confirmationRequest: ConfirmationRequest | null;
|
|
9
|
+
onSendMessage: (content: string) => void;
|
|
10
|
+
onConfirm: (actionId: string) => void;
|
|
11
|
+
onCancel: (actionId: string) => void;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
onLogout?: () => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function ChatPanel({ title, messages, isStreaming, connectionState, confirmationRequest, onSendMessage, onConfirm, onCancel, onClose, onLogout, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=ChatPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../src/components/ChatPanel.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE9E,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAChD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,QAAQ,EACR,OAAO,EACP,QAAQ,GACT,EAAE,cAAc,2CAkIhB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ConfirmationRequest } from '../types';
|
|
2
|
+
|
|
3
|
+
interface ConfirmationCardProps {
|
|
4
|
+
request: ConfirmationRequest;
|
|
5
|
+
onConfirm: (actionId: string) => void;
|
|
6
|
+
onCancel: (actionId: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function ConfirmationCard({ request, onConfirm, onCancel }: ConfirmationCardProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=ConfirmationCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfirmationCard.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,UAAU,qBAAqB;IAC7B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAsGvF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface LoginPanelProps {
|
|
2
|
+
onLoginSuccess: (jwt: string, userId: string) => void;
|
|
3
|
+
apiUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function LoginPanel({ onLoginSuccess, apiUrl }: LoginPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=LoginPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginPanel.d.ts","sourceRoot":"","sources":["../../src/components/LoginPanel.tsx"],"names":[],"mappings":"AAEA,UAAU,eAAe;IACvB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,EAAE,cAAc,EAAE,MAAmC,EAAE,EAAE,eAAe,2CA8JlG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThinkingIndicator.d.ts","sourceRoot":"","sources":["../../src/components/ThinkingIndicator.tsx"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,4CAQhC"}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Message, ConfirmationRequest, ConnectionState } from '../types';
|
|
2
|
+
|
|
3
|
+
interface UseNimWebSocketOptions {
|
|
4
|
+
wsUrl: string;
|
|
5
|
+
jwt: string | null;
|
|
6
|
+
onError?: (error: string) => void;
|
|
7
|
+
}
|
|
8
|
+
interface UseNimWebSocketReturn {
|
|
9
|
+
messages: Message[];
|
|
10
|
+
isStreaming: boolean;
|
|
11
|
+
connectionState: ConnectionState;
|
|
12
|
+
confirmationRequest: ConfirmationRequest | null;
|
|
13
|
+
sendMessage: (content: string) => void;
|
|
14
|
+
confirmAction: (actionId: string) => void;
|
|
15
|
+
cancelAction: (actionId: string) => void;
|
|
16
|
+
reconnect: () => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function useNimWebSocket({ wsUrl, jwt, onError, }: UseNimWebSocketOptions): UseNimWebSocketReturn;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=useNimWebSocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNimWebSocket.d.ts","sourceRoot":"","sources":["../../src/hooks/useNimWebSocket.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,OAAO,EAGP,mBAAmB,EACnB,eAAe,EAChB,MAAM,UAAU,CAAC;AAIlB,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAChD,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,GAAG,EACH,OAAO,GACR,EAAE,sBAAsB,GAAG,qBAAqB,CAyUhD"}
|