@agentforge-io/chat-sdk 2.4.0-dev.7 → 2.4.0-dev.9
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/ChatDrawer.js +32 -7
- package/dist/session.d.ts +1 -0
- package/dist/session.js +51 -0
- package/package.json +1 -1
package/dist/ChatDrawer.js
CHANGED
|
@@ -192,13 +192,38 @@ function ChatDrawer(props) {
|
|
|
192
192
|
// Motion / sizing portion of the surface style, kept separate from
|
|
193
193
|
// the host-supplied theming so a re-render driven by drag offset
|
|
194
194
|
// doesn't smash the host's CSS vars.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
195
|
+
//
|
|
196
|
+
// Two distinct positioning modes:
|
|
197
|
+
//
|
|
198
|
+
// **fullscreen (snap=1)**: pin the surface to the VISUAL viewport
|
|
199
|
+
// box. `top = visualViewport.offsetTop` + `height = visualViewport.h`
|
|
200
|
+
// means the drawer sits exactly on the area the user can see, with
|
|
201
|
+
// the bottom edge flush against the on-screen keyboard (when it's up)
|
|
202
|
+
// or the bottom of the screen (when it's down). No layout viewport
|
|
203
|
+
// gymnastics needed.
|
|
204
|
+
//
|
|
205
|
+
// **bottom-sheet (snap<1)**: anchor the surface to the bottom of the
|
|
206
|
+
// visual viewport. `bottom = visualViewport.offsetTop` is the legacy
|
|
207
|
+
// path that handles the rubber-band scroll case on iOS Safari.
|
|
208
|
+
const surfaceMotionStyle = fullscreen
|
|
209
|
+
? {
|
|
210
|
+
top: `${vv.offsetTop}px`,
|
|
211
|
+
height: `${vv.h}px`,
|
|
212
|
+
transform: `translate3d(0, ${translateY}, 0)`,
|
|
213
|
+
transition: isDragging
|
|
214
|
+
? 'none'
|
|
215
|
+
: 'transform 240ms cubic-bezier(.32,.72,0,1)',
|
|
216
|
+
willChange: 'transform',
|
|
217
|
+
}
|
|
218
|
+
: {
|
|
219
|
+
height: `${drawerHeight}px`,
|
|
220
|
+
transform: `translate3d(0, ${translateY}, 0)`,
|
|
221
|
+
bottom: `${vv.offsetTop}px`,
|
|
222
|
+
transition: isDragging
|
|
223
|
+
? 'none'
|
|
224
|
+
: 'transform 240ms cubic-bezier(.32,.72,0,1)',
|
|
225
|
+
willChange: 'transform',
|
|
226
|
+
};
|
|
202
227
|
return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", { className: "af-drawer-root", "data-state": open ? 'open' : 'closed', style: {
|
|
203
228
|
position: 'fixed',
|
|
204
229
|
inset: 0,
|
package/dist/session.d.ts
CHANGED
package/dist/session.js
CHANGED
|
@@ -172,6 +172,7 @@ class ChatSession {
|
|
|
172
172
|
const trimmed = text.trim();
|
|
173
173
|
if (!trimmed)
|
|
174
174
|
return '';
|
|
175
|
+
this.debug('send() called', { text: trimmed, status: this.state.status });
|
|
175
176
|
if (this.state.status === 'ended') {
|
|
176
177
|
throw new Error('Conversation has ended. Start a fresh chat to continue.');
|
|
177
178
|
}
|
|
@@ -180,6 +181,7 @@ class ChatSession {
|
|
|
180
181
|
// where the user taps Send while the initial agent/theme
|
|
181
182
|
// fetch is still in flight and conversationId is unset.
|
|
182
183
|
await this.start();
|
|
184
|
+
this.debug('send() start awaited, status=' + this.state.status);
|
|
183
185
|
if (!opts?.silent) {
|
|
184
186
|
this.appendMessage({
|
|
185
187
|
id: makeMessageId('u'),
|
|
@@ -203,6 +205,7 @@ class ChatSession {
|
|
|
203
205
|
}
|
|
204
206
|
// ─── Internals ──────────────────────────────────────────────────────────
|
|
205
207
|
async runStream(text, assistant) {
|
|
208
|
+
this.debug('runStream start', { hasConvId: !!this.state.conversationId });
|
|
206
209
|
this.setStatus('sending');
|
|
207
210
|
// The "active" message is the one we're currently appending
|
|
208
211
|
// text_deltas into. For non-team sessions it's always the initial
|
|
@@ -221,8 +224,11 @@ class ChatSession {
|
|
|
221
224
|
const generator = this.state.conversationId
|
|
222
225
|
? this.transport.streamSendMessage(this.state.conversationId, text, this.browserSessionId)
|
|
223
226
|
: this.transport.streamCreateConversation(text, this.browserSessionId);
|
|
227
|
+
this.debug('runStream got generator, awaiting events');
|
|
224
228
|
let sawAnyChunk = false;
|
|
229
|
+
let chunkCount = 0;
|
|
225
230
|
for await (const evt of generator) {
|
|
231
|
+
this.debug('SSE evt', evt.kind, chunkCount++);
|
|
226
232
|
if (evt.kind === 'conversation') {
|
|
227
233
|
this.state.conversationId = evt.id;
|
|
228
234
|
this.emit({ type: 'conversation_started', conversationId: evt.id });
|
|
@@ -398,6 +404,7 @@ class ChatSession {
|
|
|
398
404
|
cleanup(assistant);
|
|
399
405
|
if (active !== assistant)
|
|
400
406
|
cleanup(active);
|
|
407
|
+
this.debug('runStream THREW', err instanceof Error ? err.message : String(err));
|
|
401
408
|
this.handleError(err);
|
|
402
409
|
return assistant.content;
|
|
403
410
|
}
|
|
@@ -458,6 +465,50 @@ class ChatSession {
|
|
|
458
465
|
emitStateChange() {
|
|
459
466
|
this.emit({ type: 'state', state: this.getState() });
|
|
460
467
|
}
|
|
468
|
+
// Lightweight debug logger that BOTH logs to console AND appends
|
|
469
|
+
// to a visible on-screen overlay so mobile QA without remote
|
|
470
|
+
// devtools can still see what's happening. Enable by running
|
|
471
|
+
// `localStorage.setItem('af-chat-debug', '1')` in the browser
|
|
472
|
+
// console (or via the URL `?af-debug=1` once mounted) and
|
|
473
|
+
// reloading. Disabled by default so production ships clean.
|
|
474
|
+
debug(...args) {
|
|
475
|
+
try {
|
|
476
|
+
if (typeof window === 'undefined')
|
|
477
|
+
return;
|
|
478
|
+
const ls = window.localStorage;
|
|
479
|
+
let enabled = ls?.getItem('af-chat-debug') === '1';
|
|
480
|
+
if (!enabled && window.location?.search?.includes('af-debug=1')) {
|
|
481
|
+
ls?.setItem('af-chat-debug', '1');
|
|
482
|
+
enabled = true;
|
|
483
|
+
}
|
|
484
|
+
if (!enabled)
|
|
485
|
+
return;
|
|
486
|
+
const msg = args
|
|
487
|
+
.map((a) => (typeof a === 'string' ? a : JSON.stringify(a)))
|
|
488
|
+
.join(' ');
|
|
489
|
+
// eslint-disable-next-line no-console
|
|
490
|
+
console.log('[chat-sdk]', msg);
|
|
491
|
+
// Visible overlay (single shared element across all sessions).
|
|
492
|
+
let panel = document.getElementById('af-debug-panel');
|
|
493
|
+
if (!panel) {
|
|
494
|
+
panel = document.createElement('div');
|
|
495
|
+
panel.id = 'af-debug-panel';
|
|
496
|
+
panel.style.cssText =
|
|
497
|
+
'position:fixed;top:0;left:0;right:0;max-height:38vh;overflow:auto;' +
|
|
498
|
+
'background:rgba(0,0,0,0.85);color:#7CFC00;font:11px/1.3 monospace;' +
|
|
499
|
+
'padding:6px 8px;z-index:2147483647;pointer-events:auto;' +
|
|
500
|
+
'white-space:pre-wrap;word-break:break-all;';
|
|
501
|
+
document.body.appendChild(panel);
|
|
502
|
+
}
|
|
503
|
+
const line = document.createElement('div');
|
|
504
|
+
line.textContent = `${new Date().toISOString().slice(11, 23)} ${msg}`;
|
|
505
|
+
panel.appendChild(line);
|
|
506
|
+
panel.scrollTop = panel.scrollHeight;
|
|
507
|
+
}
|
|
508
|
+
catch {
|
|
509
|
+
/* localStorage can throw in private mode — ignore */
|
|
510
|
+
}
|
|
511
|
+
}
|
|
461
512
|
handleError(err) {
|
|
462
513
|
const message = err instanceof Error ? err.message : String(err);
|
|
463
514
|
const code = err && typeof err === 'object' && 'code' in err
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge-io/chat-sdk",
|
|
3
|
-
"version": "2.4.0-dev.
|
|
3
|
+
"version": "2.4.0-dev.9",
|
|
4
4
|
"description": "Framework-free chat session SDK for AgentForge public chat tokens. Headless — no DOM. Drop into any frontend (React, Vue, Svelte, vanilla) and listen for events.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|