@extrachill/chat 0.2.0 → 0.2.1
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 +53 -131
- package/dist/hooks/useChat.d.ts.map +1 -1
- package/dist/hooks/useChat.js +29 -5
- package/package.json +1 -1
- package/src/hooks/useChat.ts +23 -5
- package/dist/types/adapter.d.ts +0 -151
- package/dist/types/adapter.d.ts.map +0 -1
- package/dist/types/adapter.js +0 -11
package/README.md
CHANGED
|
@@ -1,154 +1,76 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @extrachill/chat
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React chat UI components with a built-in REST API client. Speaks the standard chat message format natively — no adapters, no wrappers.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
The goal is to provide a **standard, frontend-first, dumb chat block** that can power multiple chat experiences cleanly across different plugins and products.
|
|
10
|
-
|
|
11
|
-
This repo should focus on the **best chat experience possible** while leaving backend-specific concerns to adapters and consuming plugins.
|
|
12
|
-
|
|
13
|
-
## Why This Exists
|
|
14
|
-
|
|
15
|
-
There are already multiple chat block implementations across different repos, including:
|
|
16
|
-
|
|
17
|
-
- `Extra-Chill/extrachill-chat`
|
|
18
|
-
- `Sarai-Chinwag/spawn`
|
|
19
|
-
|
|
20
|
-
Those implementations overlap heavily in UI and runtime behavior, but differ in backend details like:
|
|
21
|
-
|
|
22
|
-
- authentication
|
|
23
|
-
- session management
|
|
24
|
-
- billing / credits
|
|
25
|
-
- agent transport
|
|
26
|
-
- provisioning / availability states
|
|
27
|
-
- branding
|
|
28
|
-
|
|
29
|
-
This repo exists to separate the **shared chat experience** from the **product-specific business logic**.
|
|
30
|
-
|
|
31
|
-
## Goals
|
|
32
|
-
|
|
33
|
-
- Build a reusable Gutenberg chat block
|
|
34
|
-
- Keep the block frontend-focused and presentation-first
|
|
35
|
-
- Support multiple backend implementations through adapters
|
|
36
|
-
- Standardize chat UX across Extra Chill projects
|
|
37
|
-
- Make it easy for WordPress plugins to become AI-native without rebuilding chat UI every time
|
|
38
|
-
|
|
39
|
-
## Non-Goals
|
|
40
|
-
|
|
41
|
-
- Owning backend AI orchestration
|
|
42
|
-
- Owning product-specific business logic
|
|
43
|
-
- Owning billing, provisioning, or auth policy
|
|
44
|
-
- Becoming a monolithic app plugin
|
|
45
|
-
|
|
46
|
-
## Proposed Architecture
|
|
47
|
-
|
|
48
|
-
```text
|
|
49
|
-
WordPress Plugin
|
|
50
|
-
|
|
|
51
|
-
| server-rendered wrapper + config
|
|
52
|
-
v
|
|
53
|
-
Shared Chat Block UI
|
|
54
|
-
|
|
|
55
|
-
| adapter contract
|
|
56
|
-
v
|
|
57
|
-
Backend-specific implementation
|
|
7
|
+
```bash
|
|
8
|
+
npm install @extrachill/chat
|
|
58
9
|
```
|
|
59
10
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
- REST endpoints
|
|
76
|
-
- authentication
|
|
77
|
-
- pricing / credit logic
|
|
78
|
-
- agent lifecycle
|
|
79
|
-
- account state
|
|
80
|
-
- server availability logic
|
|
81
|
-
- branding and product-specific rules
|
|
82
|
-
|
|
83
|
-
## Adapter Model
|
|
84
|
-
|
|
85
|
-
The main abstraction in this repo should be a narrow adapter contract.
|
|
86
|
-
|
|
87
|
-
Example shape:
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
interface ChatAdapter {
|
|
91
|
-
capabilities: {
|
|
92
|
-
sessions: boolean
|
|
93
|
-
history: boolean
|
|
94
|
-
streaming: boolean
|
|
95
|
-
tools: boolean
|
|
96
|
-
availabilityStates: boolean
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
loadInitialState?(): Promise<InitialState>
|
|
100
|
-
listSessions?(): Promise<Session[]>
|
|
101
|
-
loadMessages?(sessionId: string): Promise<Message[]>
|
|
102
|
-
createSession?(): Promise<Session>
|
|
103
|
-
sendMessage(input: SendMessageInput): Promise<SendMessageResult>
|
|
104
|
-
clearSession?(sessionId: string): Promise<void>
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { Chat } from '@extrachill/chat';
|
|
15
|
+
import '@extrachill/chat/css';
|
|
16
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
17
|
+
|
|
18
|
+
function StudioChat() {
|
|
19
|
+
return (
|
|
20
|
+
<Chat
|
|
21
|
+
basePath="/datamachine/v1/chat"
|
|
22
|
+
fetchFn={apiFetch}
|
|
23
|
+
agentId={5}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
105
26
|
}
|
|
106
27
|
```
|
|
107
28
|
|
|
108
|
-
|
|
29
|
+
## What's Included
|
|
30
|
+
|
|
31
|
+
**Components** — `Chat`, `ChatMessages`, `ChatMessage`, `ChatInput`, `TypingIndicator`, `ToolMessage`, `SessionSwitcher`, `ErrorBoundary`, `AvailabilityGate`
|
|
109
32
|
|
|
110
|
-
|
|
111
|
-
- `spawn` to use its own gateway / session model
|
|
112
|
-
- future implementations to plug in without forking the UI
|
|
33
|
+
**Hook** — `useChat` manages messages, sessions, multi-turn continuation loops, and availability state
|
|
113
34
|
|
|
114
|
-
|
|
35
|
+
**API client** — `sendMessage`, `continueResponse`, `listSessions`, `loadSession`, `deleteSession`
|
|
115
36
|
|
|
116
|
-
|
|
117
|
-
2. Build a minimal frontend-only chat block shell
|
|
118
|
-
3. Support a basic message flow end-to-end
|
|
119
|
-
4. Add optional session sidebar support
|
|
120
|
-
5. Port one real consumer first (`extrachill-chat` is likely the easiest)
|
|
121
|
-
6. Port `spawn` after the core boundaries are proven
|
|
37
|
+
**Normalizer** — `normalizeMessage`, `normalizeConversation`, `normalizeSession` for mapping raw backend messages into the UI model
|
|
122
38
|
|
|
123
|
-
|
|
39
|
+
**CSS** — `@extrachill/chat/css` provides base styles with 30+ CSS custom properties (`--ec-chat-*`) for theming
|
|
124
40
|
|
|
125
|
-
|
|
126
|
-
- create core shared block
|
|
127
|
-
- define types and adapter interfaces
|
|
128
|
-
- implement minimal mount + send + render loop
|
|
41
|
+
## REST Contract
|
|
129
42
|
|
|
130
|
-
|
|
131
|
-
- adapt `extrachill-chat` to use shared UI
|
|
132
|
-
- validate API shape and message model
|
|
43
|
+
The package expects these endpoints at `basePath`:
|
|
133
44
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
45
|
+
| Method | Path | Purpose |
|
|
46
|
+
|--------|------|---------|
|
|
47
|
+
| `POST` | `/` | Send a message (creates or continues session) |
|
|
48
|
+
| `POST` | `/continue` | Continue a multi-turn response |
|
|
49
|
+
| `GET` | `/sessions` | List sessions for the current user |
|
|
50
|
+
| `GET` | `/{session_id}` | Load a single session's conversation |
|
|
51
|
+
| `DELETE` | `/{session_id}` | Delete a session |
|
|
137
52
|
|
|
138
|
-
|
|
139
|
-
- refine styling, streaming, markdown, and extensibility
|
|
53
|
+
Any backend implementing this contract works. The `fetchFn` prop accepts any function matching `(options: { path, method?, data? }) => Promise<json>` — `@wordpress/api-fetch` works directly.
|
|
140
54
|
|
|
141
|
-
##
|
|
55
|
+
## Theming
|
|
142
56
|
|
|
143
|
-
|
|
57
|
+
Override CSS custom properties on `.ec-chat` to match your design system:
|
|
144
58
|
|
|
145
|
-
|
|
59
|
+
```css
|
|
60
|
+
.my-chat .ec-chat {
|
|
61
|
+
--ec-chat-user-bg: var(--accent);
|
|
62
|
+
--ec-chat-assistant-bg: var(--card-background);
|
|
63
|
+
--ec-chat-font-family: var(--font-family-body);
|
|
64
|
+
--ec-chat-border-radius: var(--border-radius-md);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
146
67
|
|
|
147
|
-
##
|
|
68
|
+
## Consumers
|
|
148
69
|
|
|
149
|
-
|
|
70
|
+
- **extrachill-studio** — Studio Chat tab (agent_id=5)
|
|
71
|
+
- **extrachill-chat** — chat.extrachill.com frontend
|
|
72
|
+
- **data-machine** — Admin chat sidebar
|
|
150
73
|
|
|
151
|
-
##
|
|
74
|
+
## License
|
|
152
75
|
|
|
153
|
-
-
|
|
154
|
-
- https://github.com/Sarai-Chinwag/spawn
|
|
76
|
+
GPL-2.0-or-later
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useChat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,WAAW,CAAC;AASxD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC;IAChC;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAC3C;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,gDAAgD;IAChD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,yBAAyB;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,wBAAwB;IACxB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,oCAAoC;IACpC,eAAe,EAAE,OAAO,CAAC;IACzB,2BAA2B;IAC3B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,qCAAqC;IACrC,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,4BAA4B;IAC5B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,wBAAwB;IACxB,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,oDAAoD;IACpD,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gCAAgC;IAChC,eAAe,EAAE,MAAM,IAAI,CAAC;CAC5B;
|
|
1
|
+
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useChat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,WAAW,CAAC;AASxD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC;IAChC;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAC3C;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,gDAAgD;IAChD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,yBAAyB;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,wBAAwB;IACxB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,oCAAoC;IACpC,eAAe,EAAE,OAAO,CAAC;IACzB,2BAA2B;IAC3B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,qCAAqC;IACrC,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,4BAA4B;IAC5B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,wBAAwB;IACxB,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,oDAAoD;IACpD,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gCAAgC;IAChC,eAAe,EAAE,MAAM,IAAI,CAAC;CAC5B;AAyBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,OAAO,CAAC,EACvB,QAAQ,EACR,OAAO,EACP,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,gBAAqB,EACrB,SAAS,EACT,OAAO,GACP,EAAE,cAAc,GAAG,aAAa,CAwLhC"}
|
package/dist/hooks/useChat.js
CHANGED
|
@@ -4,6 +4,30 @@ let messageIdCounter = 0;
|
|
|
4
4
|
function generateMessageId() {
|
|
5
5
|
return `msg_${Date.now()}_${++messageIdCounter}`;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Extract a readable error message from any error shape.
|
|
9
|
+
*
|
|
10
|
+
* Handles Error instances, @wordpress/api-fetch error objects
|
|
11
|
+
* ({ code, message, data }), and plain strings.
|
|
12
|
+
*/
|
|
13
|
+
function toError(err) {
|
|
14
|
+
if (err instanceof Error)
|
|
15
|
+
return err;
|
|
16
|
+
if (typeof err === 'string')
|
|
17
|
+
return new Error(err);
|
|
18
|
+
if (err && typeof err === 'object') {
|
|
19
|
+
const obj = err;
|
|
20
|
+
if (typeof obj.message === 'string')
|
|
21
|
+
return new Error(obj.message);
|
|
22
|
+
if (typeof obj.code === 'string')
|
|
23
|
+
return new Error(obj.code);
|
|
24
|
+
try {
|
|
25
|
+
return new Error(JSON.stringify(err));
|
|
26
|
+
}
|
|
27
|
+
catch { /* fall through */ }
|
|
28
|
+
}
|
|
29
|
+
return new Error('An unknown error occurred');
|
|
30
|
+
}
|
|
7
31
|
/**
|
|
8
32
|
* Core state orchestrator for the chat UI.
|
|
9
33
|
*
|
|
@@ -52,7 +76,7 @@ export function useChat({ basePath, fetchFn, agentId, initialMessages, initialSe
|
|
|
52
76
|
}
|
|
53
77
|
catch (err) {
|
|
54
78
|
// Sessions not available — degrade gracefully
|
|
55
|
-
onError?.(
|
|
79
|
+
onError?.(toError(err));
|
|
56
80
|
}
|
|
57
81
|
finally {
|
|
58
82
|
setSessionsLoading(false);
|
|
@@ -103,7 +127,7 @@ export function useChat({ basePath, fetchFn, agentId, initialMessages, initialSe
|
|
|
103
127
|
.catch(() => { });
|
|
104
128
|
}
|
|
105
129
|
catch (err) {
|
|
106
|
-
const error =
|
|
130
|
+
const error = toError(err);
|
|
107
131
|
onError?.(error);
|
|
108
132
|
// Check if it's an auth error
|
|
109
133
|
if (error.message.includes('403') || error.message.includes('rest_forbidden')) {
|
|
@@ -132,7 +156,7 @@ export function useChat({ basePath, fetchFn, agentId, initialMessages, initialSe
|
|
|
132
156
|
setMessages(loaded);
|
|
133
157
|
}
|
|
134
158
|
catch (err) {
|
|
135
|
-
onError?.(
|
|
159
|
+
onError?.(toError(err));
|
|
136
160
|
setMessages([]);
|
|
137
161
|
}
|
|
138
162
|
finally {
|
|
@@ -155,7 +179,7 @@ export function useChat({ basePath, fetchFn, agentId, initialMessages, initialSe
|
|
|
155
179
|
}
|
|
156
180
|
}
|
|
157
181
|
catch (err) {
|
|
158
|
-
onError?.(
|
|
182
|
+
onError?.(toError(err));
|
|
159
183
|
}
|
|
160
184
|
}, [onError]);
|
|
161
185
|
const clearSession = useCallback(() => {
|
|
@@ -168,7 +192,7 @@ export function useChat({ basePath, fetchFn, agentId, initialMessages, initialSe
|
|
|
168
192
|
setSessions(list);
|
|
169
193
|
}
|
|
170
194
|
catch (err) {
|
|
171
|
-
onError?.(
|
|
195
|
+
onError?.(toError(err));
|
|
172
196
|
}
|
|
173
197
|
finally {
|
|
174
198
|
setSessionsLoading(false);
|
package/package.json
CHANGED
package/src/hooks/useChat.ts
CHANGED
|
@@ -89,6 +89,24 @@ function generateMessageId(): string {
|
|
|
89
89
|
return `msg_${Date.now()}_${++messageIdCounter}`;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Extract a readable error message from any error shape.
|
|
94
|
+
*
|
|
95
|
+
* Handles Error instances, @wordpress/api-fetch error objects
|
|
96
|
+
* ({ code, message, data }), and plain strings.
|
|
97
|
+
*/
|
|
98
|
+
function toError(err: unknown): Error {
|
|
99
|
+
if (err instanceof Error) return err;
|
|
100
|
+
if (typeof err === 'string') return new Error(err);
|
|
101
|
+
if (err && typeof err === 'object') {
|
|
102
|
+
const obj = err as Record<string, unknown>;
|
|
103
|
+
if (typeof obj.message === 'string') return new Error(obj.message);
|
|
104
|
+
if (typeof obj.code === 'string') return new Error(obj.code);
|
|
105
|
+
try { return new Error(JSON.stringify(err)); } catch { /* fall through */ }
|
|
106
|
+
}
|
|
107
|
+
return new Error('An unknown error occurred');
|
|
108
|
+
}
|
|
109
|
+
|
|
92
110
|
/**
|
|
93
111
|
* Core state orchestrator for the chat UI.
|
|
94
112
|
*
|
|
@@ -148,7 +166,7 @@ export function useChat({
|
|
|
148
166
|
setSessions(list);
|
|
149
167
|
} catch (err) {
|
|
150
168
|
// Sessions not available — degrade gracefully
|
|
151
|
-
onError?.(
|
|
169
|
+
onError?.(toError(err));
|
|
152
170
|
} finally {
|
|
153
171
|
setSessionsLoading(false);
|
|
154
172
|
}
|
|
@@ -217,7 +235,7 @@ export function useChat({
|
|
|
217
235
|
.catch(() => { /* ignore */ });
|
|
218
236
|
|
|
219
237
|
} catch (err) {
|
|
220
|
-
const error =
|
|
238
|
+
const error = toError(err);
|
|
221
239
|
onError?.(error);
|
|
222
240
|
|
|
223
241
|
// Check if it's an auth error
|
|
@@ -248,7 +266,7 @@ export function useChat({
|
|
|
248
266
|
const loaded = await apiLoadSession(configRef.current, newSessionId);
|
|
249
267
|
setMessages(loaded);
|
|
250
268
|
} catch (err) {
|
|
251
|
-
onError?.(
|
|
269
|
+
onError?.(toError(err));
|
|
252
270
|
setMessages([]);
|
|
253
271
|
} finally {
|
|
254
272
|
setIsLoading(false);
|
|
@@ -272,7 +290,7 @@ export function useChat({
|
|
|
272
290
|
setMessages([]);
|
|
273
291
|
}
|
|
274
292
|
} catch (err) {
|
|
275
|
-
onError?.(
|
|
293
|
+
onError?.(toError(err));
|
|
276
294
|
}
|
|
277
295
|
}, [onError]);
|
|
278
296
|
|
|
@@ -286,7 +304,7 @@ export function useChat({
|
|
|
286
304
|
const list = await apiListSessions(configRef.current);
|
|
287
305
|
setSessions(list);
|
|
288
306
|
} catch (err) {
|
|
289
|
-
onError?.(
|
|
307
|
+
onError?.(toError(err));
|
|
290
308
|
} finally {
|
|
291
309
|
setSessionsLoading(false);
|
|
292
310
|
}
|
package/dist/types/adapter.d.ts
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The adapter contract.
|
|
3
|
-
*
|
|
4
|
-
* This is the main abstraction boundary. The shared chat UI calls
|
|
5
|
-
* adapter methods — it never knows about REST endpoints, auth tokens,
|
|
6
|
-
* WebSocket connections, or billing logic.
|
|
7
|
-
*
|
|
8
|
-
* Adapters declare their capabilities so the UI can conditionally
|
|
9
|
-
* render features like session switching or tool display.
|
|
10
|
-
*/
|
|
11
|
-
import type { ChatMessage } from './message.ts';
|
|
12
|
-
import type { ChatSession, ChatInitialState } from './session.ts';
|
|
13
|
-
/**
|
|
14
|
-
* Capability flags. The UI uses these to conditionally render features.
|
|
15
|
-
*/
|
|
16
|
-
export interface ChatCapabilities {
|
|
17
|
-
/** Adapter supports multiple named sessions. */
|
|
18
|
-
sessions: boolean;
|
|
19
|
-
/** Adapter can load historical messages for a session. */
|
|
20
|
-
history: boolean;
|
|
21
|
-
/** Adapter supports real-time streaming of responses. */
|
|
22
|
-
streaming: boolean;
|
|
23
|
-
/** Adapter exposes tool call/result messages. */
|
|
24
|
-
tools: boolean;
|
|
25
|
-
/** Adapter surfaces availability states (login, provisioning, etc.). */
|
|
26
|
-
availabilityStates: boolean;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Input to the sendMessage method.
|
|
30
|
-
*/
|
|
31
|
-
export interface SendMessageInput {
|
|
32
|
-
/** The user's message text. */
|
|
33
|
-
content: string;
|
|
34
|
-
/** Session to send to (undefined = create new or use default). */
|
|
35
|
-
sessionId?: string;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Result from a sendMessage call.
|
|
39
|
-
*
|
|
40
|
-
* The response can include multiple messages (e.g. tool calls + final answer).
|
|
41
|
-
* If `completed` is false, the UI should call `continueResponse` to get more.
|
|
42
|
-
*/
|
|
43
|
-
export interface SendMessageResult {
|
|
44
|
-
/** The session this message belongs to (may be newly created). */
|
|
45
|
-
sessionId: string;
|
|
46
|
-
/** New messages to append to the conversation. */
|
|
47
|
-
messages: ChatMessage[];
|
|
48
|
-
/** Whether the response is fully complete. */
|
|
49
|
-
completed: boolean;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Result from a continueResponse call.
|
|
53
|
-
*/
|
|
54
|
-
export interface ContinueResult {
|
|
55
|
-
/** New messages from this turn. */
|
|
56
|
-
messages: ChatMessage[];
|
|
57
|
-
/** Whether the response is now fully complete. */
|
|
58
|
-
completed: boolean;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Callback for streaming chunks.
|
|
62
|
-
*/
|
|
63
|
-
export interface StreamChunk {
|
|
64
|
-
/** Partial content delta. */
|
|
65
|
-
content: string;
|
|
66
|
-
/** Whether this is the final chunk. */
|
|
67
|
-
done: boolean;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* The adapter contract.
|
|
71
|
-
*
|
|
72
|
-
* Only `sendMessage` and `capabilities` are required. Everything else
|
|
73
|
-
* is optional — the UI degrades gracefully based on capabilities.
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```ts
|
|
77
|
-
* const adapter: ChatAdapter = {
|
|
78
|
-
* capabilities: {
|
|
79
|
-
* sessions: false,
|
|
80
|
-
* history: false,
|
|
81
|
-
* streaming: false,
|
|
82
|
-
* tools: false,
|
|
83
|
-
* availabilityStates: false,
|
|
84
|
-
* },
|
|
85
|
-
* async sendMessage(input) {
|
|
86
|
-
* const res = await fetch('/api/chat', {
|
|
87
|
-
* method: 'POST',
|
|
88
|
-
* body: JSON.stringify({ message: input.content }),
|
|
89
|
-
* });
|
|
90
|
-
* const data = await res.json();
|
|
91
|
-
* return {
|
|
92
|
-
* sessionId: 'default',
|
|
93
|
-
* messages: [{ id: data.id, role: 'assistant', content: data.reply, timestamp: new Date().toISOString() }],
|
|
94
|
-
* completed: true,
|
|
95
|
-
* };
|
|
96
|
-
* },
|
|
97
|
-
* };
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
export interface ChatAdapter {
|
|
101
|
-
/** Declare what this adapter supports. */
|
|
102
|
-
capabilities: ChatCapabilities;
|
|
103
|
-
/**
|
|
104
|
-
* Load initial state on mount.
|
|
105
|
-
* Returns availability, optional active session, and messages.
|
|
106
|
-
* If not provided, the UI assumes `{ availability: { status: 'ready' } }`.
|
|
107
|
-
*/
|
|
108
|
-
loadInitialState?(): Promise<ChatInitialState>;
|
|
109
|
-
/**
|
|
110
|
-
* Send a user message and get the response.
|
|
111
|
-
* This is the only required async method.
|
|
112
|
-
*/
|
|
113
|
-
sendMessage(input: SendMessageInput): Promise<SendMessageResult>;
|
|
114
|
-
/**
|
|
115
|
-
* Continue a multi-turn response (tool calling, etc.).
|
|
116
|
-
* Called when `sendMessage` returns `completed: false`.
|
|
117
|
-
* If not provided, multi-turn is not supported.
|
|
118
|
-
*/
|
|
119
|
-
continueResponse?(sessionId: string): Promise<ContinueResult>;
|
|
120
|
-
/**
|
|
121
|
-
* Subscribe to streaming response chunks.
|
|
122
|
-
* Called instead of polling when `capabilities.streaming` is true.
|
|
123
|
-
* Returns an unsubscribe function.
|
|
124
|
-
*/
|
|
125
|
-
onStream?(sessionId: string, callback: (chunk: StreamChunk) => void): () => void;
|
|
126
|
-
/**
|
|
127
|
-
* List available sessions.
|
|
128
|
-
* Only called when `capabilities.sessions` is true.
|
|
129
|
-
*/
|
|
130
|
-
listSessions?(limit?: number): Promise<ChatSession[]>;
|
|
131
|
-
/**
|
|
132
|
-
* Load messages for a specific session.
|
|
133
|
-
* Only called when `capabilities.history` is true.
|
|
134
|
-
*/
|
|
135
|
-
loadMessages?(sessionId: string): Promise<ChatMessage[]>;
|
|
136
|
-
/**
|
|
137
|
-
* Create a new empty session.
|
|
138
|
-
* Only called when `capabilities.sessions` is true.
|
|
139
|
-
*/
|
|
140
|
-
createSession?(): Promise<ChatSession>;
|
|
141
|
-
/**
|
|
142
|
-
* Delete a session.
|
|
143
|
-
* Only called when `capabilities.sessions` is true.
|
|
144
|
-
*/
|
|
145
|
-
deleteSession?(sessionId: string): Promise<void>;
|
|
146
|
-
/**
|
|
147
|
-
* Clear all messages in a session (without deleting it).
|
|
148
|
-
*/
|
|
149
|
-
clearSession?(sessionId: string): Promise<void>;
|
|
150
|
-
}
|
|
151
|
-
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/types/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,KAAK,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IACjC,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,mCAAmC;IACnC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,kDAAkD;IAClD,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,IAAI,EAAE,OAAO,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,WAAW;IAC3B,0CAA0C;IAC1C,YAAY,EAAE,gBAAgB,CAAC;IAE/B;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE/C;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAEjE;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAE9D;;;;OAIG;IACH,QAAQ,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAEjF;;;OAGG;IACH,YAAY,CAAC,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEtD;;;OAGG;IACH,YAAY,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEzD;;;OAGG;IACH,aAAa,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;IAEvC;;;OAGG;IACH,aAAa,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;OAEG;IACH,YAAY,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD"}
|
package/dist/types/adapter.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The adapter contract.
|
|
3
|
-
*
|
|
4
|
-
* This is the main abstraction boundary. The shared chat UI calls
|
|
5
|
-
* adapter methods — it never knows about REST endpoints, auth tokens,
|
|
6
|
-
* WebSocket connections, or billing logic.
|
|
7
|
-
*
|
|
8
|
-
* Adapters declare their capabilities so the UI can conditionally
|
|
9
|
-
* render features like session switching or tool display.
|
|
10
|
-
*/
|
|
11
|
-
export {};
|