bloby-bot 0.23.4 → 0.23.6

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.
@@ -1 +1 @@
1
- import{c as e,r as t,t as n}from"./jsx-runtime-C0W9Wf2W.js";import{n as r,r as i,t as a}from"./bloby-C0a7vrLL.js";var o=e(t(),1),s=n(),c=({code:e,language:t,raw:n,className:c,startLine:l,lineNumbers:u,...d})=>{let{shikiTheme:f}=(0,o.useContext)(i),p=r(),[m,h]=(0,o.useState)(n);return(0,o.useEffect)(()=>{if(!p){h(n);return}let r=p.highlight({code:e,language:t,themes:f},e=>{h(e)});r&&h(r)},[e,t,f,p,n]),(0,s.jsx)(a,{className:c,language:t,lineNumbers:u,result:m,startLine:l,...d})};export{c as HighlightedCodeBlockBody};
1
+ import{c as e,r as t,t as n}from"./jsx-runtime-C0W9Wf2W.js";import{n as r,r as i,t as a}from"./bloby-D5KNR5Eq.js";var o=e(t(),1),s=n(),c=({code:e,language:t,raw:n,className:c,startLine:l,lineNumbers:u,...d})=>{let{shikiTheme:f}=(0,o.useContext)(i),p=r(),[m,h]=(0,o.useState)(n);return(0,o.useEffect)(()=>{if(!p){h(n);return}let r=p.highlight({code:e,language:t,themes:f},e=>{h(e)});r&&h(r)},[e,t,f,p,n]),(0,s.jsx)(a,{className:c,language:t,lineNumbers:u,result:m,startLine:l,...d})};export{c as HighlightedCodeBlockBody};
@@ -0,0 +1 @@
1
+ import{i as e}from"./bloby-D5KNR5Eq.js";export{e as Mermaid};
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content" />
6
6
  <title>Bloby Chat</title>
7
- <script type="module" crossorigin src="/bloby/assets/bloby-C0a7vrLL.js"></script>
7
+ <script type="module" crossorigin src="/bloby/assets/bloby-D5KNR5Eq.js"></script>
8
8
  <link rel="modulepreload" crossorigin href="/bloby/assets/jsx-runtime-C0W9Wf2W.js">
9
9
  <link rel="modulepreload" crossorigin href="/bloby/assets/globals-F7yBpvwG.js">
10
10
  <link rel="stylesheet" crossorigin href="/bloby/assets/globals-CLC60WUS.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bloby-bot",
3
- "version": "0.23.4",
3
+ "version": "0.23.6",
4
4
  "releaseNotes": [
5
5
  "1. new stuff",
6
6
  "2. ",
@@ -94,6 +94,14 @@ export function hasConversation(conversationId: string): boolean {
94
94
  return liveConversations.has(conversationId);
95
95
  }
96
96
 
97
+ /** End all live conversations (e.g. after re-auth so they restart with fresh token) */
98
+ export function endAllConversations(): void {
99
+ for (const convId of liveConversations.keys()) {
100
+ log.info(`[conversation] Ending conversation ${convId} (auth changed)`);
101
+ endConversation(convId);
102
+ }
103
+ }
104
+
97
105
  // ── Helpers ─────────────────────────────────────────────────────────────────
98
106
 
99
107
  /** Read a memory file from workspace, returning '(empty)' if missing or empty */
@@ -170,16 +170,21 @@ export class ChannelManager {
170
170
  if (images.length > 0 && provider instanceof WhatsAppChannel) {
171
171
  for (const img of images) {
172
172
  try {
173
- // Resolve the file path from the /api/files/ URL
173
+ // Resolve file path try multiple locations since the bot might save anywhere
174
174
  const relPath = img.src.replace(/^\/api\/files\//, '');
175
- const absPath = path.join(WORKSPACE_DIR, relPath);
176
- if (fs.existsSync(absPath)) {
175
+ const candidates = [
176
+ path.join(WORKSPACE_DIR, 'files', relPath), // /api/files/images/x.png → workspace/files/images/x.png
177
+ path.join(WORKSPACE_DIR, relPath), // /x.png → workspace/x.png
178
+ path.join(WORKSPACE_DIR, 'client', 'public', relPath), // /x.png → workspace/client/public/x.png
179
+ ];
180
+ const absPath = candidates.find((p) => fs.existsSync(p));
181
+ if (absPath) {
177
182
  const buffer = fs.readFileSync(absPath);
178
183
  const ext = path.extname(absPath).slice(1);
179
184
  const mimeMap: Record<string, string> = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', webp: 'image/webp' };
180
185
  await provider.sendImage(to, buffer, img.alt || undefined, mimeMap[ext] || 'image/png');
181
186
  } else {
182
- log.warn(`[channels] Image file not found: ${absPath}`);
187
+ log.warn(`[channels] Image file not found in any location: ${img.src}`);
183
188
  }
184
189
  } catch (err: any) {
185
190
  log.warn(`[channels] Failed to send image via WhatsApp: ${err.message}`);
@@ -1,4 +1,5 @@
1
- import { Download } from 'lucide-react';
1
+ import { useState } from 'react';
2
+ import { Download, ImageOff } from 'lucide-react';
2
3
 
3
4
  interface Props {
4
5
  src: string;
@@ -11,6 +12,8 @@ function getFilename(src: string): string {
11
12
  }
12
13
 
13
14
  export default function BlobyImageCard({ src, alt }: Props) {
15
+ const [failed, setFailed] = useState(false);
16
+
14
17
  const handleDownload = async () => {
15
18
  try {
16
19
  const res = await fetch(src);
@@ -28,6 +31,15 @@ export default function BlobyImageCard({ src, alt }: Props) {
28
31
  }
29
32
  };
30
33
 
34
+ if (failed) {
35
+ return (
36
+ <div className="my-2 flex items-center gap-2.5 px-3.5 py-2.5 rounded-xl border border-border/30 bg-black/10 text-muted-foreground/50 text-xs">
37
+ <ImageOff className="h-4 w-4 shrink-0" />
38
+ <span className="truncate">{alt || 'Image not found'}</span>
39
+ </div>
40
+ );
41
+ }
42
+
31
43
  return (
32
44
  <div className="relative group/img my-2 rounded-xl overflow-hidden border border-border/30 bg-black/20 w-fit max-w-full">
33
45
  <img
@@ -35,6 +47,7 @@ export default function BlobyImageCard({ src, alt }: Props) {
35
47
  alt={alt || 'Generated image'}
36
48
  className="max-w-full max-h-80 object-contain"
37
49
  loading="lazy"
50
+ onError={() => setFailed(true)}
38
51
  />
39
52
  <div className="absolute top-2 right-2 flex gap-1.5 opacity-0 group-hover/img:opacity-100 transition-opacity">
40
53
  <button
@@ -14,7 +14,7 @@ import { closeDb, getSession, getSetting } from '../worker/db.js';
14
14
  import { spawnBackend, stopBackend, getBackendPort, isBackendAlive, isBackendStopping, resetBackendRestarts } from './backend.js';
15
15
  import { updateTunnelUrl, startHeartbeat, stopHeartbeat, disconnect } from '../shared/relay.js';
16
16
  import {
17
- startConversation, pushMessage, hasConversation, endConversation,
17
+ startConversation, pushMessage, hasConversation, endConversation, endAllConversations,
18
18
  isConversationBusy, stopSubAgentTask,
19
19
  startBlobyAgentQuery, stopBlobyAgentQuery,
20
20
  type RecentMessage,
@@ -687,6 +687,24 @@ ${!connected ? '<script>setTimeout(()=>location.reload(),4000)</script>' : ''}
687
687
  }
688
688
  }
689
689
 
690
+ // After successful Claude re-auth, end live conversations so they restart with a fresh token
691
+ if (req.method === 'POST' && req.url === '/api/auth/claude/exchange') {
692
+ const origEnd = res.end.bind(res);
693
+ (res as any).end = function (this: typeof res, ...args: any[]) {
694
+ try {
695
+ const body = typeof args[0] === 'string' ? args[0] : args[0]?.toString();
696
+ if (body) {
697
+ const json = JSON.parse(body);
698
+ if (json.success) {
699
+ log.info('[orchestrator] Claude re-auth succeeded — restarting conversations with fresh token');
700
+ endAllConversations();
701
+ }
702
+ }
703
+ } catch {}
704
+ return origEnd(...args);
705
+ };
706
+ }
707
+
690
708
  workerApp(req, res);
691
709
  return;
692
710
  }
@@ -942,6 +960,9 @@ ${!connected ? '<script>setTimeout(()=>location.reload(),4000)</script>' : ''}
942
960
  (async () => {
943
961
  try {
944
962
  const result = await workerApi('/api/onboard', 'POST', msg.data);
963
+ // Settings change may affect model/provider/token — restart conversations
964
+ log.info('[orchestrator] Settings saved — restarting conversations');
965
+ endAllConversations();
945
966
  if (ws.readyState === WebSocket.OPEN) {
946
967
  ws.send(JSON.stringify({ type: 'settings:saved', data: result }));
947
968
  }
@@ -1 +0,0 @@
1
- import{i as e}from"./bloby-C0a7vrLL.js";export{e as Mermaid};