bunnyquery 1.0.2 → 1.0.4

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.
Files changed (2) hide show
  1. package/bunnyquery.js +60 -4
  2. package/package.json +1 -1
package/bunnyquery.js CHANGED
@@ -36,7 +36,7 @@
36
36
  // The embed has no build-time env, so we always point at the production
37
37
  // MCP host. Override BunnyQuery.MCP_BASE_URL before init() to swap.
38
38
  const DEFAULTS = {
39
- MCP_BASE_URL: 'https://mcp-dev.broadwayinc.computer',
39
+ MCP_BASE_URL: 'https://mcp.broadwayinc.computer',
40
40
  MCP_NAME: 'BunnyQuery',
41
41
  DEFAULT_CLAUDE_MODEL: 'claude-sonnet-4-6',
42
42
  DEFAULT_OPENAI_MODEL: 'gpt-5.4',
@@ -470,6 +470,44 @@
470
470
  return typeof c === 'string' ? c : '';
471
471
  }
472
472
 
473
+ // Mirror of agent.vue's getErrorMessage — pulls the most useful string
474
+ // out of either a thrown error or an error-shaped response body.
475
+ function getErrorMessage(err) {
476
+ if (typeof err === 'string') return err;
477
+ if (err && err.body && err.body.error && typeof err.body.error.message === 'string') {
478
+ return err.body.error.message;
479
+ }
480
+ if (err && err.error && typeof err.error.message === 'string') {
481
+ return err.error.message;
482
+ }
483
+ if (err && typeof err.message === 'string') return err.message;
484
+ return 'Request failed. Please try again.';
485
+ }
486
+
487
+ // Mirror of agent.vue's isErrorResponseBody — detects provider/proxy
488
+ // error payloads that should render as a red error bubble even when
489
+ // no exception was thrown.
490
+ function isErrorResponseBody(response) {
491
+ if (!response || typeof response !== 'object') return false;
492
+ if (typeof response.status_code === 'number' && response.status_code >= 400) return true;
493
+ if (response.type === 'error') return true;
494
+ if (response.error && (response.error.message || response.error.type)) return true;
495
+ const body = response.body;
496
+ if (body && typeof body === 'object') {
497
+ if (body.type === 'error') return true;
498
+ if (body.error && (body.error.message || body.error.type)) return true;
499
+ }
500
+ if (typeof response.message === 'string' && response.message.length) {
501
+ const hasClaudeBody = Array.isArray(response.content);
502
+ const hasOpenAIBody =
503
+ typeof response.output_text === 'string' ||
504
+ Array.isArray(response.output) ||
505
+ Array.isArray(response.choices);
506
+ if (!hasClaudeBody && !hasOpenAIBody) return true;
507
+ }
508
+ return false;
509
+ }
510
+
473
511
  // Walk the persisted history list returned by clientSecretRequestHistory
474
512
  // and turn it into a flat user/assistant list ordered oldest -> newest.
475
513
  function mapHistoryToMessages(list, platform) {
@@ -500,10 +538,10 @@
500
538
 
501
539
  if (item.status === 'pending') {
502
540
  out.push({ role: 'assistant', content: '', id: item.id, isPending: true });
503
- } else if (item.status === 'failed' || (res && res.error)) {
541
+ } else if (item.status === 'failed' || isErrorResponseBody(res)) {
504
542
  out.push({
505
543
  role: 'assistant',
506
- content: (res && res.error && res.error.message) || 'Request failed.',
544
+ content: getErrorMessage(res),
507
545
  id: item.id,
508
546
  isError: true,
509
547
  });
@@ -1295,6 +1333,24 @@
1295
1333
  ? await buildClaudeRequest(this.skapi, args)
1296
1334
  : await buildOpenAIRequest(this.skapi, args);
1297
1335
 
1336
+ // The proxy may resolve with an error-shaped body instead of
1337
+ // throwing; surface that as an error bubble with the
1338
+ // upstream message rather than dropping it.
1339
+ if (isErrorResponseBody(result)) {
1340
+ const errMsg = getErrorMessage(result);
1341
+ const last = this.messages[this.messages.length - 1];
1342
+ if (last && last.isPending) {
1343
+ last.isPending = false;
1344
+ last.isError = true;
1345
+ last.content = errMsg;
1346
+ } else {
1347
+ this.messages.push({ role: 'assistant', content: errMsg, isError: true });
1348
+ }
1349
+ this._renderMessages();
1350
+ this._schedulePendingPoll();
1351
+ return;
1352
+ }
1353
+
1298
1354
  const responseText = this.platform === 'claude'
1299
1355
  ? extractClaudeText(result)
1300
1356
  : extractOpenAIText(result);
@@ -1311,7 +1367,7 @@
1311
1367
  this._schedulePendingPoll();
1312
1368
  } catch (err) {
1313
1369
  const last = this.messages[this.messages.length - 1];
1314
- const errMsg = (err && err.message) || String(err);
1370
+ const errMsg = getErrorMessage(err);
1315
1371
  if (last && last.isPending) {
1316
1372
  last.isPending = false;
1317
1373
  last.isError = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunnyquery",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "BunnyQuery AI chat client",
5
5
  "main": "bunnyquery.js",
6
6
  "files": [