@optima-chat/agentic-sdk 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/dist/client/conversation-api.d.ts +23 -0
- package/dist/client/conversation-api.d.ts.map +1 -0
- package/dist/client/conversation-api.js +207 -0
- package/dist/client/conversation-api.js.map +1 -0
- package/dist/client/error-mapper.d.ts +5 -0
- package/dist/client/error-mapper.d.ts.map +1 -0
- package/dist/client/error-mapper.js +19 -0
- package/dist/client/error-mapper.js.map +1 -0
- package/dist/client/event-parser.d.ts +79 -0
- package/dist/client/event-parser.d.ts.map +1 -0
- package/dist/client/event-parser.js +219 -0
- package/dist/client/event-parser.js.map +1 -0
- package/dist/client/gateway-client.d.ts +45 -0
- package/dist/client/gateway-client.d.ts.map +1 -0
- package/dist/client/gateway-client.js +172 -0
- package/dist/client/gateway-client.js.map +1 -0
- package/dist/hooks/use-approval.d.ts +8 -0
- package/dist/hooks/use-approval.d.ts.map +1 -0
- package/dist/hooks/use-approval.js +39 -0
- package/dist/hooks/use-approval.js.map +1 -0
- package/dist/hooks/use-connection-state.d.ts +7 -0
- package/dist/hooks/use-connection-state.d.ts.map +1 -0
- package/dist/hooks/use-connection-state.js +12 -0
- package/dist/hooks/use-connection-state.js.map +1 -0
- package/dist/hooks/use-conversations.d.ts +12 -0
- package/dist/hooks/use-conversations.d.ts.map +1 -0
- package/dist/hooks/use-conversations.js +42 -0
- package/dist/hooks/use-conversations.js.map +1 -0
- package/dist/hooks/use-current-chat.d.ts +14 -0
- package/dist/hooks/use-current-chat.d.ts.map +1 -0
- package/dist/hooks/use-current-chat.js +142 -0
- package/dist/hooks/use-current-chat.js.map +1 -0
- package/dist/hooks/use-question.d.ts +7 -0
- package/dist/hooks/use-question.d.ts.map +1 -0
- package/dist/hooks/use-question.js +17 -0
- package/dist/hooks/use-question.js.map +1 -0
- package/dist/hooks/use-session.d.ts +7 -0
- package/dist/hooks/use-session.d.ts.map +1 -0
- package/dist/hooks/use-session.js +13 -0
- package/dist/hooks/use-session.js.map +1 -0
- package/dist/hooks/use-switch-config.d.ts +7 -0
- package/dist/hooks/use-switch-config.d.ts.map +1 -0
- package/dist/hooks/use-switch-config.js +30 -0
- package/dist/hooks/use-switch-config.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/provider/chat-context.d.ts +14 -0
- package/dist/provider/chat-context.d.ts.map +1 -0
- package/dist/provider/chat-context.js +10 -0
- package/dist/provider/chat-context.js.map +1 -0
- package/dist/provider/chat-provider.d.ts +16 -0
- package/dist/provider/chat-provider.d.ts.map +1 -0
- package/dist/provider/chat-provider.js +200 -0
- package/dist/provider/chat-provider.js.map +1 -0
- package/dist/store/chat-store.d.ts +65 -0
- package/dist/store/chat-store.d.ts.map +1 -0
- package/dist/store/chat-store.js +220 -0
- package/dist/store/chat-store.js.map +1 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace/default-provider.d.ts +14 -0
- package/dist/workspace/default-provider.d.ts.map +1 -0
- package/dist/workspace/default-provider.js +46 -0
- package/dist/workspace/default-provider.js.map +1 -0
- package/dist/workspace/types.d.ts +11 -0
- package/dist/workspace/types.d.ts.map +1 -0
- package/dist/workspace/types.js +2 -0
- package/dist/workspace/types.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket client for the Optima gateway. Handles connect/reconnect,
|
|
3
|
+
* heartbeat, token-refresh signalling, and event dispatch. Does not own any
|
|
4
|
+
* state — everything flows out via the callbacks.
|
|
5
|
+
*/
|
|
6
|
+
export class GatewayClient {
|
|
7
|
+
options;
|
|
8
|
+
ws = null;
|
|
9
|
+
heartbeatTimer = null;
|
|
10
|
+
reconnectTimer = null;
|
|
11
|
+
reconnectAttempt = 0;
|
|
12
|
+
intentionalDisconnect = false;
|
|
13
|
+
reconnectConfig;
|
|
14
|
+
heartbeatInterval;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
this.reconnectConfig = {
|
|
18
|
+
maxRetries: options.reconnectOptions?.maxRetries ?? 5,
|
|
19
|
+
baseDelay: options.reconnectOptions?.baseDelay ?? 2000,
|
|
20
|
+
maxDelay: options.reconnectOptions?.maxDelay ?? 30000,
|
|
21
|
+
};
|
|
22
|
+
this.heartbeatInterval = options.heartbeatInterval ?? 30000;
|
|
23
|
+
}
|
|
24
|
+
async connect() {
|
|
25
|
+
this.intentionalDisconnect = false;
|
|
26
|
+
this.options.onConnectionStateChange('connecting');
|
|
27
|
+
await this.openSocket();
|
|
28
|
+
}
|
|
29
|
+
disconnect() {
|
|
30
|
+
this.intentionalDisconnect = true;
|
|
31
|
+
this.stopHeartbeat();
|
|
32
|
+
if (this.reconnectTimer !== null) {
|
|
33
|
+
clearTimeout(this.reconnectTimer);
|
|
34
|
+
this.reconnectTimer = null;
|
|
35
|
+
}
|
|
36
|
+
if (this.ws) {
|
|
37
|
+
try {
|
|
38
|
+
this.ws.close();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
/* noop */
|
|
42
|
+
}
|
|
43
|
+
this.ws = null;
|
|
44
|
+
}
|
|
45
|
+
this.options.onConnectionStateChange('disconnected');
|
|
46
|
+
}
|
|
47
|
+
/** Returns true if the event was dispatched, false otherwise. */
|
|
48
|
+
send(event) {
|
|
49
|
+
const transformed = this.options.onBeforeSend
|
|
50
|
+
? this.options.onBeforeSend(event)
|
|
51
|
+
: event;
|
|
52
|
+
if (transformed === null)
|
|
53
|
+
return false;
|
|
54
|
+
const ws = this.ws;
|
|
55
|
+
if (!ws || ws.readyState !== 1 /* OPEN */)
|
|
56
|
+
return false;
|
|
57
|
+
ws.send(JSON.stringify(transformed));
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
/** Exposed so ChatProvider can trigger token refresh manually if needed. */
|
|
61
|
+
async handleTokenRefresh() {
|
|
62
|
+
try {
|
|
63
|
+
const token = await this.options.tokenProvider();
|
|
64
|
+
this.send({
|
|
65
|
+
type: 'update_token',
|
|
66
|
+
token,
|
|
67
|
+
user: { userId: '' },
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
this.options.onAuthError({
|
|
72
|
+
code: 'auth_expired',
|
|
73
|
+
message: err instanceof Error ? err.message : 'Token provider failed',
|
|
74
|
+
});
|
|
75
|
+
this.disconnect();
|
|
76
|
+
this.options.onConnectionStateChange('auth_failed');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ---- internals ----
|
|
80
|
+
async openSocket() {
|
|
81
|
+
let token;
|
|
82
|
+
try {
|
|
83
|
+
token = await this.options.tokenProvider();
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
this.options.onAuthError({
|
|
87
|
+
code: 'auth_expired',
|
|
88
|
+
message: err instanceof Error ? err.message : 'Token fetch failed',
|
|
89
|
+
});
|
|
90
|
+
this.options.onConnectionStateChange('auth_failed');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const separator = this.options.gatewayUrl.includes('?') ? '&' : '?';
|
|
94
|
+
const url = `${this.options.gatewayUrl}${separator}token=${encodeURIComponent(token)}`;
|
|
95
|
+
const ws = new WebSocket(url);
|
|
96
|
+
this.ws = ws;
|
|
97
|
+
await new Promise((resolve) => {
|
|
98
|
+
ws.onopen = () => {
|
|
99
|
+
this.reconnectAttempt = 0;
|
|
100
|
+
this.options.onConnectionStateChange('connected');
|
|
101
|
+
this.startHeartbeat();
|
|
102
|
+
resolve();
|
|
103
|
+
};
|
|
104
|
+
ws.onclose = () => {
|
|
105
|
+
this.stopHeartbeat();
|
|
106
|
+
if (this.intentionalDisconnect) {
|
|
107
|
+
this.options.onConnectionStateChange('disconnected');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (this.reconnectAttempt >= this.reconnectConfig.maxRetries) {
|
|
111
|
+
this.options.onConnectionStateChange('disconnected');
|
|
112
|
+
this.options.onError({
|
|
113
|
+
code: 'reconnect_exhausted',
|
|
114
|
+
message: 'WebSocket reconnect retries exhausted',
|
|
115
|
+
retryable: false,
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
this.options.onConnectionStateChange('reconnecting');
|
|
120
|
+
this.scheduleReconnect();
|
|
121
|
+
// Resolve so the caller's connect() promise doesn't hang forever; the
|
|
122
|
+
// consumer observes the state change via the callback.
|
|
123
|
+
resolve();
|
|
124
|
+
};
|
|
125
|
+
ws.onerror = () => {
|
|
126
|
+
// `onclose` will follow; handle reconnect there.
|
|
127
|
+
};
|
|
128
|
+
ws.onmessage = (ev) => this.handleMessage(ev);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
handleMessage(ev) {
|
|
132
|
+
let event;
|
|
133
|
+
try {
|
|
134
|
+
event = JSON.parse(String(ev.data));
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Always forward to consumer — they may route it to rawEvent.
|
|
140
|
+
this.options.onEvent(event);
|
|
141
|
+
// Internal handling: token_refresh_needed triggers a refresh+send cycle.
|
|
142
|
+
if (event.type === 'token_refresh_needed') {
|
|
143
|
+
void this.handleTokenRefresh();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
scheduleReconnect() {
|
|
147
|
+
const attempt = this.reconnectAttempt;
|
|
148
|
+
this.reconnectAttempt = attempt + 1;
|
|
149
|
+
const base = Math.min(this.reconnectConfig.baseDelay * Math.pow(2, attempt), this.reconnectConfig.maxDelay);
|
|
150
|
+
// Jitter: scale by random factor in [0.5, 1.0].
|
|
151
|
+
const delay = base * (0.5 + Math.random() * 0.5);
|
|
152
|
+
this.reconnectTimer = setTimeout(() => {
|
|
153
|
+
this.reconnectTimer = null;
|
|
154
|
+
void this.openSocket();
|
|
155
|
+
}, delay);
|
|
156
|
+
}
|
|
157
|
+
startHeartbeat() {
|
|
158
|
+
this.stopHeartbeat();
|
|
159
|
+
this.heartbeatTimer = setInterval(() => {
|
|
160
|
+
if (this.ws && this.ws.readyState === 1 /* OPEN */) {
|
|
161
|
+
this.send({ type: 'ping' });
|
|
162
|
+
}
|
|
163
|
+
}, this.heartbeatInterval);
|
|
164
|
+
}
|
|
165
|
+
stopHeartbeat() {
|
|
166
|
+
if (this.heartbeatTimer !== null) {
|
|
167
|
+
clearInterval(this.heartbeatTimer);
|
|
168
|
+
this.heartbeatTimer = null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=gateway-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../../src/client/gateway-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ApprovalRequestWithId } from '../types.js';
|
|
2
|
+
export declare function useApproval(): {
|
|
3
|
+
pendingApprovals: ApprovalRequestWithId[];
|
|
4
|
+
approve: (requestId: string) => void;
|
|
5
|
+
reject: (requestId: string, reason?: string) => void;
|
|
6
|
+
modify: (requestId: string, modifiedArgs: Record<string, unknown>, message?: string) => void;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=use-approval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-approval.d.ts","sourceRoot":"","sources":["../../src/hooks/use-approval.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,wBAAgB,WAAW,IAAI;IAC7B,gBAAgB,EAAE,qBAAqB,EAAE,CAAC;IAC1C,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,MAAM,EAAE,CACN,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,OAAO,CAAC,EAAE,MAAM,KACb,IAAI,CAAC;CACX,CAmDA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useStore } from 'zustand';
|
|
3
|
+
import { useChatContext } from '../provider/chat-context.js';
|
|
4
|
+
export function useApproval() {
|
|
5
|
+
const { store, client } = useChatContext();
|
|
6
|
+
const pendingApprovals = useStore(store, (s) => s.pendingApprovals);
|
|
7
|
+
const approve = useCallback((requestId) => {
|
|
8
|
+
client.send({
|
|
9
|
+
type: 'approval_response',
|
|
10
|
+
approval: { requestId, decision: 'approved' },
|
|
11
|
+
});
|
|
12
|
+
store.getState().removePendingApproval(requestId);
|
|
13
|
+
}, [client, store]);
|
|
14
|
+
const reject = useCallback((requestId, reason) => {
|
|
15
|
+
client.send({
|
|
16
|
+
type: 'approval_response',
|
|
17
|
+
approval: {
|
|
18
|
+
requestId,
|
|
19
|
+
decision: 'denied',
|
|
20
|
+
...(reason !== undefined ? { message: reason } : {}),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
store.getState().removePendingApproval(requestId);
|
|
24
|
+
}, [client, store]);
|
|
25
|
+
const modify = useCallback((requestId, modifiedArgs, message) => {
|
|
26
|
+
client.send({
|
|
27
|
+
type: 'approval_response',
|
|
28
|
+
approval: {
|
|
29
|
+
requestId,
|
|
30
|
+
decision: 'modified',
|
|
31
|
+
modifiedArgs,
|
|
32
|
+
...(message !== undefined ? { message } : {}),
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
store.getState().removePendingApproval(requestId);
|
|
36
|
+
}, [client, store]);
|
|
37
|
+
return { pendingApprovals, approve, reject, modify };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=use-approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-approval.js","sourceRoot":"","sources":["../../src/hooks/use-approval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,MAAM,UAAU,WAAW;IAUzB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC3C,MAAM,gBAAgB,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAEpE,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,SAAiB,EAAE,EAAE;QACpB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE;SAC9C,CAAC,CAAC;QACH,KAAK,CAAC,QAAQ,EAAE,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,SAAiB,EAAE,MAAe,EAAE,EAAE;QACrC,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE;gBACR,SAAS;gBACT,QAAQ,EAAE,QAAQ;gBAClB,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrD;SACF,CAAC,CAAC;QACH,KAAK,CAAC,QAAQ,EAAE,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,CACxB,CACE,SAAiB,EACjB,YAAqC,EACrC,OAAgB,EAChB,EAAE;QACF,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE;gBACR,SAAS;gBACT,QAAQ,EAAE,UAAU;gBACpB,YAAY;gBACZ,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9C;SACF,CAAC,CAAC;QACH,KAAK,CAAC,QAAQ,EAAE,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-connection-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-connection-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,wBAAgB,kBAAkB,IAAI;IACpC,eAAe,EAAE,eAAe,CAAC;IACjC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAUA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useStore } from 'zustand';
|
|
2
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
3
|
+
import { useChatContext } from '../provider/chat-context.js';
|
|
4
|
+
export function useConnectionState() {
|
|
5
|
+
const { store } = useChatContext();
|
|
6
|
+
return useStore(store, useShallow((s) => ({
|
|
7
|
+
connectionState: s.connectionState,
|
|
8
|
+
error: s.connectionError,
|
|
9
|
+
reconnectAttempt: s.reconnectAttempt,
|
|
10
|
+
})));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=use-connection-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-connection-state.js","sourceRoot":"","sources":["../../src/hooks/use-connection-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,MAAM,UAAU,kBAAkB;IAKhC,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,EAAE,CAAC;IACnC,OAAO,QAAQ,CACb,KAAK,EACL,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjB,eAAe,EAAE,CAAC,CAAC,eAAe;QAClC,KAAK,EAAE,CAAC,CAAC,eAAe;QACxB,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;KACrC,CAAC,CAAC,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChatError, Conversation } from '../types.js';
|
|
2
|
+
export declare function useConversations(): {
|
|
3
|
+
conversations: Conversation[];
|
|
4
|
+
currentConversationId: string | null;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
error: ChatError | null;
|
|
7
|
+
createConversation: (title?: string) => Promise<Conversation>;
|
|
8
|
+
deleteConversation: (conversationId: string) => Promise<void>;
|
|
9
|
+
renameConversation: (conversationId: string, title: string) => Promise<void>;
|
|
10
|
+
switchConversation: (conversationId: string) => void;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=use-conversations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-conversations.d.ts","sourceRoot":"","sources":["../../src/hooks/use-conversations.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3D,wBAAgB,gBAAgB,IAAI;IAClC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,kBAAkB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9D,kBAAkB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,kBAAkB,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,kBAAkB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD,CAwDA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useStore } from 'zustand';
|
|
3
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
4
|
+
import { useChatContext } from '../provider/chat-context.js';
|
|
5
|
+
export function useConversations() {
|
|
6
|
+
const { store, client, api } = useChatContext();
|
|
7
|
+
const state = useStore(store, useShallow((s) => ({
|
|
8
|
+
conversations: s.conversations,
|
|
9
|
+
currentConversationId: s.currentConversationId,
|
|
10
|
+
isLoading: s.conversationsLoading,
|
|
11
|
+
error: s.conversationsError,
|
|
12
|
+
})));
|
|
13
|
+
const createConversation = useCallback(async (title) => {
|
|
14
|
+
const conversation = await api.createConversation(title);
|
|
15
|
+
store.getState().addConversation(conversation);
|
|
16
|
+
return conversation;
|
|
17
|
+
}, [api, store]);
|
|
18
|
+
// Delete/rename go through the WebSocket — gateway persists and re-broadcasts.
|
|
19
|
+
const deleteConversation = useCallback(async (conversationId) => {
|
|
20
|
+
client.send({ type: 'delete_conversation', conversation_id: conversationId });
|
|
21
|
+
store.getState().removeConversation(conversationId);
|
|
22
|
+
}, [client, store]);
|
|
23
|
+
const renameConversation = useCallback(async (conversationId, title) => {
|
|
24
|
+
client.send({
|
|
25
|
+
type: 'rename_conversation',
|
|
26
|
+
conversation_id: conversationId,
|
|
27
|
+
title,
|
|
28
|
+
});
|
|
29
|
+
store.getState().updateConversationTitle(conversationId, title);
|
|
30
|
+
}, [client, store]);
|
|
31
|
+
const switchConversation = useCallback((conversationId) => {
|
|
32
|
+
store.getState().setCurrentConversationId(conversationId);
|
|
33
|
+
}, [store]);
|
|
34
|
+
return {
|
|
35
|
+
...state,
|
|
36
|
+
createConversation,
|
|
37
|
+
deleteConversation,
|
|
38
|
+
renameConversation,
|
|
39
|
+
switchConversation,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=use-conversations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-conversations.js","sourceRoot":"","sources":["../../src/hooks/use-conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,MAAM,UAAU,gBAAgB;IAU9B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,QAAQ,CACpB,KAAK,EACL,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjB,aAAa,EAAE,CAAC,CAAC,aAAa;QAC9B,qBAAqB,EAAE,CAAC,CAAC,qBAAqB;QAC9C,SAAS,EAAE,CAAC,CAAC,oBAAoB;QACjC,KAAK,EAAE,CAAC,CAAC,kBAAkB;KAC5B,CAAC,CAAC,CACJ,CAAC;IAEF,MAAM,kBAAkB,GAAG,WAAW,CACpC,KAAK,EAAE,KAAc,EAAE,EAAE;QACvB,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACzD,KAAK,CAAC,QAAQ,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QAC/C,OAAO,YAAY,CAAC;IACtB,CAAC,EACD,CAAC,GAAG,EAAE,KAAK,CAAC,CACb,CAAC;IAEF,+EAA+E;IAC/E,MAAM,kBAAkB,GAAG,WAAW,CACpC,KAAK,EAAE,cAAsB,EAAE,EAAE;QAC/B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC,CAAC;QAC9E,KAAK,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IACtD,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,kBAAkB,GAAG,WAAW,CACpC,KAAK,EAAE,cAAsB,EAAE,KAAa,EAAE,EAAE;QAC9C,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,qBAAqB;YAC3B,eAAe,EAAE,cAAc;YAC/B,KAAK;SACN,CAAC,CAAC;QACH,KAAK,CAAC,QAAQ,EAAE,CAAC,uBAAuB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,kBAAkB,GAAG,WAAW,CACpC,CAAC,cAAsB,EAAE,EAAE;QACzB,KAAK,CAAC,QAAQ,EAAE,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAC5D,CAAC,EACD,CAAC,KAAK,CAAC,CACR,CAAC;IAEF,OAAO;QACL,GAAG,KAAK;QACR,kBAAkB;QAClB,kBAAkB;QAClB,kBAAkB;QAClB,kBAAkB;KACnB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ChatError, Message, SendMessageOptions } from '../types.js';
|
|
2
|
+
export declare function useCurrentChat(): {
|
|
3
|
+
messages: Message[];
|
|
4
|
+
isStreaming: boolean;
|
|
5
|
+
isThinking: boolean;
|
|
6
|
+
error: ChatError | null;
|
|
7
|
+
sendMessage: (content: string, options?: SendMessageOptions) => Promise<void>;
|
|
8
|
+
abort: () => void;
|
|
9
|
+
resetConversation: () => Promise<void>;
|
|
10
|
+
loadHistory: () => Promise<void>;
|
|
11
|
+
hasMoreHistory: boolean;
|
|
12
|
+
isLoadingHistory: boolean;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=use-current-chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-current-chat.d.ts","sourceRoot":"","sources":["../../src/hooks/use-current-chat.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAEP,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAQrB,wBAAgB,cAAc,IAAI;IAChC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAgJA"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useStore } from 'zustand';
|
|
3
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
4
|
+
import { useChatContext } from '../provider/chat-context.js';
|
|
5
|
+
// Stable empty-array reference for missing message lists — avoids creating
|
|
6
|
+
// new array references in the selector (which would break shallow equality
|
|
7
|
+
// and, under React 19, trigger "getSnapshot should be cached" warnings).
|
|
8
|
+
const EMPTY_MESSAGES = [];
|
|
9
|
+
Object.freeze(EMPTY_MESSAGES);
|
|
10
|
+
export function useCurrentChat() {
|
|
11
|
+
const { store, client, api, workspaceProvider } = useChatContext();
|
|
12
|
+
const conversationId = useStore(store, (s) => s.currentConversationId);
|
|
13
|
+
const state = useStore(store, useShallow((s) => {
|
|
14
|
+
const id = s.currentConversationId;
|
|
15
|
+
return {
|
|
16
|
+
messages: id ? (s.messages[id] ?? EMPTY_MESSAGES) : EMPTY_MESSAGES,
|
|
17
|
+
isStreaming: s.isStreaming,
|
|
18
|
+
isThinking: s.isThinking,
|
|
19
|
+
error: s.currentChatError,
|
|
20
|
+
hasMoreHistory: id ? (s.hasMoreHistory[id] ?? true) : false,
|
|
21
|
+
isLoadingHistory: s.historyLoading,
|
|
22
|
+
};
|
|
23
|
+
}));
|
|
24
|
+
const sendMessage = useCallback(async (content, options) => {
|
|
25
|
+
if (!conversationId)
|
|
26
|
+
throw new Error('No active conversation');
|
|
27
|
+
const contentParts = { text: content };
|
|
28
|
+
const attachments = [];
|
|
29
|
+
if (options?.images?.length) {
|
|
30
|
+
if (!workspaceProvider) {
|
|
31
|
+
throw new Error('workspaceProvider is required to send images');
|
|
32
|
+
}
|
|
33
|
+
const results = await workspaceProvider.uploadFiles(options.images);
|
|
34
|
+
contentParts.images = results.map((r) => ({
|
|
35
|
+
url: r.url,
|
|
36
|
+
mediaType: r.mediaType,
|
|
37
|
+
}));
|
|
38
|
+
for (const r of results) {
|
|
39
|
+
attachments.push({
|
|
40
|
+
type: 'image',
|
|
41
|
+
url: r.url,
|
|
42
|
+
name: r.originalName,
|
|
43
|
+
mediaType: r.mediaType,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (options?.files?.length) {
|
|
48
|
+
if (!workspaceProvider) {
|
|
49
|
+
throw new Error('workspaceProvider is required to send files');
|
|
50
|
+
}
|
|
51
|
+
const results = await workspaceProvider.uploadFiles(options.files);
|
|
52
|
+
contentParts.files = results.map((r) => ({
|
|
53
|
+
url: r.url,
|
|
54
|
+
filename: r.originalName,
|
|
55
|
+
mediaType: r.mediaType,
|
|
56
|
+
}));
|
|
57
|
+
for (const r of results) {
|
|
58
|
+
attachments.push({
|
|
59
|
+
type: 'file',
|
|
60
|
+
url: r.url,
|
|
61
|
+
name: r.originalName,
|
|
62
|
+
mediaType: r.mediaType,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (options?.audio?.length) {
|
|
67
|
+
if (!workspaceProvider) {
|
|
68
|
+
throw new Error('workspaceProvider is required to send audio');
|
|
69
|
+
}
|
|
70
|
+
const results = await workspaceProvider.uploadFiles(options.audio);
|
|
71
|
+
for (const r of results) {
|
|
72
|
+
attachments.push({
|
|
73
|
+
type: 'audio',
|
|
74
|
+
url: r.url,
|
|
75
|
+
name: r.originalName,
|
|
76
|
+
mediaType: r.mediaType,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const userMessageId = crypto.randomUUID();
|
|
81
|
+
store.getState().addMessage(conversationId, {
|
|
82
|
+
id: userMessageId,
|
|
83
|
+
conversationId,
|
|
84
|
+
role: 'user',
|
|
85
|
+
content,
|
|
86
|
+
toolCalls: [],
|
|
87
|
+
...(attachments.length > 0 ? { attachments } : {}),
|
|
88
|
+
status: 'complete',
|
|
89
|
+
createdAt: Date.now(),
|
|
90
|
+
});
|
|
91
|
+
const sent = client.send({
|
|
92
|
+
type: 'message',
|
|
93
|
+
conversation_id: conversationId,
|
|
94
|
+
content,
|
|
95
|
+
contentParts,
|
|
96
|
+
...(options?.metadata !== undefined ? { metadata: options.metadata } : {}),
|
|
97
|
+
});
|
|
98
|
+
if (!sent)
|
|
99
|
+
throw new Error('Failed to send message');
|
|
100
|
+
store.getState().setThinking(true);
|
|
101
|
+
}, [conversationId, client, store, workspaceProvider]);
|
|
102
|
+
const abort = useCallback(() => {
|
|
103
|
+
if (!conversationId)
|
|
104
|
+
return;
|
|
105
|
+
client.send({ type: 'abort', conversation_id: conversationId });
|
|
106
|
+
}, [conversationId, client]);
|
|
107
|
+
const resetConversation = useCallback(async () => {
|
|
108
|
+
if (!conversationId)
|
|
109
|
+
return;
|
|
110
|
+
client.send({ type: 'reset_conversation', conversation_id: conversationId });
|
|
111
|
+
}, [conversationId, client]);
|
|
112
|
+
const loadHistory = useCallback(async () => {
|
|
113
|
+
if (!conversationId)
|
|
114
|
+
return;
|
|
115
|
+
if (state.isLoadingHistory || !state.hasMoreHistory)
|
|
116
|
+
return;
|
|
117
|
+
store.getState().setHistoryLoading(true);
|
|
118
|
+
try {
|
|
119
|
+
const offset = store.getState().historyOffset[conversationId] ?? 0;
|
|
120
|
+
const messages = await api.getMessages(conversationId, {
|
|
121
|
+
skip: offset,
|
|
122
|
+
take: 50,
|
|
123
|
+
});
|
|
124
|
+
store.getState().prependMessages(conversationId, messages);
|
|
125
|
+
store
|
|
126
|
+
.getState()
|
|
127
|
+
.setHistoryOffset(conversationId, offset + messages.length);
|
|
128
|
+
store.getState().setHasMoreHistory(conversationId, messages.length === 50);
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
store.getState().setHistoryLoading(false);
|
|
132
|
+
}
|
|
133
|
+
}, [conversationId, api, store, state.isLoadingHistory, state.hasMoreHistory]);
|
|
134
|
+
return {
|
|
135
|
+
...state,
|
|
136
|
+
sendMessage,
|
|
137
|
+
abort,
|
|
138
|
+
resetConversation,
|
|
139
|
+
loadHistory,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=use-current-chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-current-chat.js","sourceRoot":"","sources":["../../src/hooks/use-current-chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { QuestionRequest } from '../types.js';
|
|
2
|
+
export declare function useQuestion(): {
|
|
3
|
+
pendingQuestion: QuestionRequest | null;
|
|
4
|
+
answerQuestion: (requestId: string, answers: Record<string, string>) => void;
|
|
5
|
+
dismissQuestion: (requestId: string) => void;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=use-question.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-question.d.ts","sourceRoot":"","sources":["../../src/hooks/use-question.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,wBAAgB,WAAW,IAAI;IAC7B,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC7E,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAqBA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useStore } from 'zustand';
|
|
3
|
+
import { useChatContext } from '../provider/chat-context.js';
|
|
4
|
+
export function useQuestion() {
|
|
5
|
+
const { store, client } = useChatContext();
|
|
6
|
+
const pendingQuestion = useStore(store, (s) => s.pendingQuestion);
|
|
7
|
+
const answerQuestion = useCallback((requestId, answers) => {
|
|
8
|
+
client.send({ type: 'answer_question', request_id: requestId, answers });
|
|
9
|
+
store.getState().setPendingQuestion(null);
|
|
10
|
+
}, [client, store]);
|
|
11
|
+
const dismissQuestion = useCallback((requestId) => {
|
|
12
|
+
client.send({ type: 'answer_question', request_id: requestId, answers: {} });
|
|
13
|
+
store.getState().setPendingQuestion(null);
|
|
14
|
+
}, [client, store]);
|
|
15
|
+
return { pendingQuestion, answerQuestion, dismissQuestion };
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=use-question.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-question.js","sourceRoot":"","sources":["../../src/hooks/use-question.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,MAAM,UAAU,WAAW;IAKzB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC3C,MAAM,eAAe,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAElE,MAAM,cAAc,GAAG,WAAW,CAChC,CAAC,SAAiB,EAAE,OAA+B,EAAE,EAAE;QACrD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;QACzE,KAAK,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,SAAiB,EAAE,EAAE;QACpB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAC7E,KAAK,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-session.d.ts","sourceRoot":"","sources":["../../src/hooks/use-session.ts"],"names":[],"mappings":"AAIA,wBAAgB,UAAU,IAAI;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAWA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useStore } from 'zustand';
|
|
2
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
3
|
+
import { useChatContext } from '../provider/chat-context.js';
|
|
4
|
+
export function useSession() {
|
|
5
|
+
const { store } = useChatContext();
|
|
6
|
+
return useStore(store, useShallow((s) => ({
|
|
7
|
+
sessionId: s.sessionId,
|
|
8
|
+
userId: s.userId,
|
|
9
|
+
provider: s.provider,
|
|
10
|
+
model: s.model,
|
|
11
|
+
})));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=use-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-session.js","sourceRoot":"","sources":["../../src/hooks/use-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,MAAM,UAAU,UAAU;IAMxB,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,EAAE,CAAC;IACnC,OAAO,QAAQ,CACb,KAAK,EACL,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjB,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,CAAC,CAAC,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-switch-config.d.ts","sourceRoot":"","sources":["../../src/hooks/use-switch-config.ts"],"names":[],"mappings":"AAIA,wBAAgB,eAAe,IAAI;IACjC,YAAY,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACvE,CA+BA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useStore } from 'zustand';
|
|
3
|
+
import { useChatContext } from '../provider/chat-context.js';
|
|
4
|
+
export function useSwitchConfig() {
|
|
5
|
+
const { store, client } = useChatContext();
|
|
6
|
+
const currentConversationId = useStore(store, (s) => s.currentConversationId);
|
|
7
|
+
const switchConfig = useCallback((config) => {
|
|
8
|
+
// 1. Send switch_config over the existing WebSocket.
|
|
9
|
+
client.send({
|
|
10
|
+
type: 'switch_config',
|
|
11
|
+
...(config.provider !== undefined ? { provider: config.provider } : {}),
|
|
12
|
+
...(config.model !== undefined ? { model: config.model } : {}),
|
|
13
|
+
...(currentConversationId
|
|
14
|
+
? { conversation_id: currentConversationId }
|
|
15
|
+
: {}),
|
|
16
|
+
});
|
|
17
|
+
// 2. Optimistic store update so useSession() reflects the new choice
|
|
18
|
+
// immediately; gateway confirmation via a later session_ready (if any)
|
|
19
|
+
// can overwrite this.
|
|
20
|
+
const state = store.getState();
|
|
21
|
+
state.setSessionInfo({
|
|
22
|
+
sessionId: state.sessionId ?? '',
|
|
23
|
+
userId: state.userId ?? '',
|
|
24
|
+
provider: config.provider ?? state.provider ?? undefined,
|
|
25
|
+
model: config.model ?? state.model ?? undefined,
|
|
26
|
+
});
|
|
27
|
+
}, [client, store, currentConversationId]);
|
|
28
|
+
return { switchConfig };
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=use-switch-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-switch-config.js","sourceRoot":"","sources":["../../src/hooks/use-switch-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,MAAM,UAAU,eAAe;IAG7B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC3C,MAAM,qBAAqB,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;IAE9E,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,MAA6C,EAAE,EAAE;QAChD,qDAAqD;QACrD,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,eAAe;YACrB,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,qBAAqB;gBACvB,CAAC,CAAC,EAAE,eAAe,EAAE,qBAAqB,EAAE;gBAC5C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;QAEH,qEAAqE;QACrE,uEAAuE;QACvE,sBAAsB;QACtB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC/B,KAAK,CAAC,cAAc,CAAC;YACnB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,EAAE;YAChC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;YAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,SAAS;YACxD,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,SAAS;SAChD,CAAC,CAAC;IACL,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,EAAE,qBAAqB,CAAC,CACvC,CAAC;IAEF,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC"}
|