@whoz-oss/coday-web 0.18.2 → 0.18.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.
package/client/index.html CHANGED
@@ -9,5 +9,5 @@
9
9
  <style>:root{--color-bg:#f8f8f2;--color-bg-secondary:#f1f1eb;--color-text:#282a36;--color-text-secondary:#6272a4;--color-text-inverse:#ffffff;--color-primary:#7064fb;--color-primary-hover:#ff79c6;--color-link:#3498db;--color-border:#aeaeae;--color-input-bg:#ffffff;--color-success:#50fa7b;--color-error:#ff5555;--color-warning:#ffb86c;--color-info:#8be9fd;--color-message-user:#e2dee2;--color-message-ai:#e8ecf6;--color-code-bg:#f1f1f1;--color-code-text:#d63384;--color-bg-hover:#f1f3f4;--color-shadow:rgba(0, 0, 0, .1);--color-overlay:rgba(0, 0, 0, .3)}*{box-sizing:border-box}html,body{margin:0;padding:0;width:100%;height:100%}body{background-color:var(--color-bg, #f8f8f2);color:var(--color-text, #282a36);font-family:system-ui,sans-serif;transition:background-color .2s ease,color .2s ease}</style><link rel="stylesheet" href="styles-BJ6YBRRX.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-BJ6YBRRX.css"></noscript></head>
10
10
  <body>
11
11
  <app-root></app-root>
12
- <script src="polyfills-B6TNHZQ6.js" type="module"></script><script src="main-HYHKC5LJ.js" type="module"></script></body>
12
+ <script src="polyfills-B6TNHZQ6.js" type="module"></script><script src="main-EBP2SAFU.js" type="module"></script></body>
13
13
  </html>
@@ -70,7 +70,7 @@ Please report this to https://github.com/markedjs/marked.`,n){let r="<p>An error
70
70
  `;t.push(s)}return t.join("")})}onPlay(){let e=this.getTextContentForVoice();if(!e.trim()){console.warn("[CHAT-MESSAGE] No text content to play");return}if(this.isPlaying)console.log("[CHAT-MESSAGE] Stopping current playback"),this.voiceSynthesisService.stopSpeech(),this.isPlaying=!1;else{console.log("[CHAT-MESSAGE] Starting playback for message:",this.message.id);let t=()=>{console.log("[CHAT-MESSAGE] Playback ended for message:",this.message.id),this.isPlaying=!1};this.voiceSynthesisService.speak(e,t).then(r=>{r?this.isPlaying=!0:console.warn("[CHAT-MESSAGE] Failed to start speech synthesis")}).catch(r=>{console.error("[CHAT-MESSAGE] Error during speech synthesis:",r),this.isPlaying=!1})}this.playRequested.emit(this.message)}onCopy(){let e=this.getTextContentForVoice();e.trim()&&navigator.clipboard.writeText(e).then(()=>{console.log("[CHAT-MESSAGE] Message copied to clipboard")}).catch(t=>{console.error("[CHAT-MESSAGE] Failed to copy message:",t)}),this.copyRequested.emit(this.message)}onDelete(){console.log("[CHAT-MESSAGE] Delete requested for message:",this.message.id),this.deleteRequested.emit(this.message)}onMessageClick(){this.voiceSynthesisService.isSpeaking()&&this.voiceSynthesisService.stopSpeech()}getTextContentForVoice(){return this.extractTextContent()}extractTextContent(){return this.message.content.filter(e=>e.type==="text").map(e=>e.content).join(`
71
71
 
72
72
  `)}static \u0275fac=function(t){return new(t||n)};static \u0275cmp=_e({type:n,selectors:[["app-chat-message"]],inputs:{message:"message",canDelete:"canDelete"},outputs:{playRequested:"playRequested",copyRequested:"copyRequested",deleteRequested:"deleteRequested"},decls:3,vars:4,consts:[["tabindex","0","role","button",1,"message",3,"click","keydown.enter","keydown.space","ngClass"],[4,"ngIf"],[1,"message-header"],["class","speaker",4,"ngIf"],["class","actions",4,"ngIf"],[1,"content","markdown-content",3,"innerHTML"],[1,"speaker"],[1,"actions"],[1,"action-btn","play-btn",3,"click","title"],["title","Copy message",1,"action-btn",3,"click"],["class","action-btn delete-btn","title","Delete this message and all following messages",3,"click",4,"ngIf"],["title","Delete this message and all following messages",1,"action-btn","delete-btn",3,"click"],[1,"simple-content","markdown-content"],[3,"innerHTML"],["target","_blank","class","event-link",3,"href","click",4,"ngIf"],["target","_blank",1,"event-link",3,"click","href"]],template:function(t,r){t&1&&(v(0,"div",0),M("click",function(){return r.onMessageClick()})("keydown.enter",function(){return r.onMessageClick()})("keydown.space",function(){return r.onMessageClick()}),re(1,cO,5,3,"ng-container",1)(2,dO,4,2,"ng-container",1),m()),t&2&&(A("ngClass",r.messageClasses),si("aria-label","Message from "+r.message.speaker+". Click to stop speech if playing."),E(),A("ngIf",!r.isSimplified),E(),A("ngIf",r.isSimplified))},dependencies:[Se,Hp,ke],styles:[".message[_ngcontent-%COMP%]{margin:.5rem 0;border-radius:8px;position:relative;max-width:75%;width:fit-content;min-width:100px;word-wrap:break-word;cursor:pointer}.message.user[_ngcontent-%COMP%]{padding:.75rem 1rem;background:var(--color-message-user, #e2dee2);margin-left:auto;margin-right:0;border-bottom-right-radius:4px}.message.assistant[_ngcontent-%COMP%]{padding:.75rem 1rem;background:var(--color-message-ai, #e8ecf6);margin-left:0;margin-right:auto;border-bottom-left-radius:4px}.message.system[_ngcontent-%COMP%], .message.technical[_ngcontent-%COMP%]{padding:.25rem 0;background:transparent;border:none;margin:.25rem 0;font-family:monospace;font-size:.85rem;color:var(--color-text-secondary, #6272a4);max-width:none;width:auto;min-width:auto;cursor:default}.message.error[_ngcontent-%COMP%]{padding:.75rem;background:#ff55551a;border-left:3px solid var(--color-error, #ff5555);color:var(--color-error, #ff5555)}.message.warning[_ngcontent-%COMP%]{padding:.75rem;background:#ffb86c1a;border-left:3px solid var(--color-warning, #ffb86c);color:var(--color-warning, #ffb86c)}.message-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem}.speaker[_ngcontent-%COMP%]{font-weight:600;font-size:.85rem;color:var(--color-text-secondary, #6272a4)}.content[_ngcontent-%COMP%]{line-height:1.5}.actions[_ngcontent-%COMP%]{display:flex;gap:.5rem;opacity:0;transition:opacity .2s}.message[_ngcontent-%COMP%]:hover .actions[_ngcontent-%COMP%]{opacity:1}.simple-content[_ngcontent-%COMP%]{display:flex}.simple-content[_ngcontent-%COMP%] .event-link[_ngcontent-%COMP%]{margin-left:5px;font-size:.9em;color:var(--color-link, #3498db);text-decoration:none}.simple-content[_ngcontent-%COMP%] .event-link[_ngcontent-%COMP%]:hover{text-decoration:underline}.action-btn[_ngcontent-%COMP%]{background:none;border:1px solid var(--color-border, #aeaeae);border-radius:3px;padding:.2rem .4rem;cursor:pointer;font-size:.7rem;transition:all .2s ease}.action-btn[_ngcontent-%COMP%]:hover{background:var(--color-bg-secondary, #f1f1eb);transform:scale(1.05)}.action-btn[_ngcontent-%COMP%]:active{transform:scale(.95)}.delete-btn[_ngcontent-%COMP%]{border-color:var(--color-error, #ff5555);color:var(--color-error, #ff5555)}.delete-btn[_ngcontent-%COMP%]:hover{background:#ff55551a;border-color:var(--color-error, #ff5555);transform:scale(1.05)}.delete-btn[_ngcontent-%COMP%]:active{background:#f553;transform:scale(.95)}.play-btn.playing[_ngcontent-%COMP%]{background:var(--color-primary, #7064fb);color:#fff;border-color:var(--color-primary, #7064fb)}.play-btn.playing[_ngcontent-%COMP%]:hover{background:var(--color-primary-hover, #5a4df5);border-color:var(--color-primary-hover, #5a4df5)}.text-part[_ngcontent-%COMP%]{margin:4px 0}.image-content[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:center;margin:1em 0}.message-image[_ngcontent-%COMP%]{display:block;max-width:100%;height:auto;margin:8px 0;border-radius:8px;cursor:pointer;box-shadow:0 2px 8px #0000001a;transition:transform .2s ease,box-shadow .2s ease}.message-image[_ngcontent-%COMP%]:hover{opacity:.9;transform:scale(1.02);box-shadow:0 4px 16px #0003}@media (max-width: 768px){.message-image[_ngcontent-%COMP%]{border-radius:4px;margin:6px 0}}@media (max-width: 480px){.message-image[_ngcontent-%COMP%]{margin:4px 0}}"]})};var Oo=class n{unreadCountSubject=new V(0);unreadCount$=this.unreadCountSubject.asObservable();constructor(){console.log("[UNREAD] Service initialized")}addUnread(){let t=this.unreadCountSubject.value+1;this.unreadCountSubject.next(t),console.log("[UNREAD] Added unread message, total:",t)}markAllAsRead(){this.unreadCountSubject.value>0&&(this.unreadCountSubject.next(0),console.log("[UNREAD] Marked all messages as read"))}getCurrentCount(){return this.unreadCountSubject.value}reset(){this.unreadCountSubject.next(0),console.log("[UNREAD] Counter reset")}static \u0275fac=function(t){return new(t||n)};static \u0275prov=C({token:n,factory:n.\u0275fac,providedIn:"root"})};function Rw(n,e=80){if(n.length<=e)return n;try{if(n.trim().startsWith("{")||n.trim().startsWith("[")){let t=JSON.parse(n),r=JSON.stringify(t);return r.length<=e?r:r.substring(0,e)+`...(${r.length} chars)`}}catch{}return n.substring(0,e)+"..."}var dt=class{constructor(e,t){this.type=t;if(e.timestamp)this.timestamp=e.timestamp;else{let r=Math.random().toString(36).substring(2,7);this.timestamp=`${new Date().toISOString()}-${r}`}this.parentKey=e.parentKey,this.length=0}timestamp;parentKey;static type;length},qu=class extends dt{invite;constructor(e,t){super(e,t),this.invite=e.invite}buildAnswer(e){return new Tr({answer:e,parentKey:this.timestamp,invite:this.invite})}},ko=class n extends dt{static type="heartbeat";constructor(e){super(e,n.type)}},Po=class n extends qu{defaultValue;static type="invite";constructor(e){super(e,n.type),this.defaultValue=e.defaultValue}},Tr=class n extends dt{answer;invite;static type="answer";constructor(e){super(e,n.type),this.answer=e.answer??"No answer",this.invite=e.invite}},Fo=class n extends dt{speaker;text;static type="text";constructor(e){super(e,n.type),this.speaker=e.speaker,this.text=e.text}},Lo=class n extends dt{warning;static type="warn";constructor(e){super(e,n.type),this.warning=e.warning}},Kn=class n extends dt{error;static type="error";constructor(e){super(e,n.type),this.error=e.error}},Vo=class n extends qu{options;optionalQuestion;static type="choice";constructor(e){super(e,n.type),this.options=e.options,this.optionalQuestion=e.optionalQuestion}},jo=class n extends dt{toolRequestId;name;args;static type="tool_request";constructor(e){super(e,n.type),this.toolRequestId=e.toolRequestId??this.timestamp,this.name=e.name,this.args=e.args,this.length=this.args.length+this.name.length+this.toolRequestId.length+20}buildResponse(e){return new Si({output:e,toolRequestId:this.toolRequestId,parentKey:this.timestamp})}toSingleLineString(e=50){let t=Rw(this.args,e);return`\u{1F527} ${this.name}(${t})`}},Si=class n extends dt{toolRequestId;output;static type="tool_response";constructor(e){if(super(e,n.type),this.toolRequestId=e.toolRequestId||this.timestamp||new Date().toISOString(),this.output=e.output,typeof this.output=="string")this.length=this.output.length+this.toolRequestId.length+20;else if(this.output.type==="text")this.length=this.output.content.length+this.toolRequestId.length+20;else if(this.output.type==="image"){let t=(this.output.width??0)*(this.output.height??0)/750;this.length=(t?t*3.5:this.output.content.length)+this.toolRequestId.length+20}else this.length=this.toolRequestId.length+20}getTextOutput(){return typeof this.output=="string"?this.output:this.output.type==="text"?this.output.content:this.output.type==="image"?`[Image: ${this.output.mimeType}]`:""}toSingleLineString(e=50){let t=this.getTextOutput(),r=Rw(t,e),i=typeof this.output!="string"&&this.output.type==="image"?" [image]":"";return`\u2B91 ${r}${i}`}},Ir=class n extends dt{projectName;static type="project_selected";constructor(e){super(e,n.type),this.projectName=e.projectName}},Mr=class n extends dt{threadId;threadName;static type="thread_selected";constructor(e){super(e,n.type),this.threadId=e.threadId,this.threadName=e.threadName}},Ti=class n extends dt{static type="thinking";static debounce=5e3;constructor(e){super(e,n.type)}},Bo=class n extends dt{role;name;content;static type="message";constructor(e){super(e,n.type),this.role=e.role,this.name=e.name,this.content=e.content,this.length=this.content.map(t=>{if(t.type==="text")return t.content.length;if(t.type==="image"){let r=(t.width||0)*(t.height||0)/750;return r?r*3.5:t.content.length}return 0}).reduce((t,r)=>t+r,0)}getTextContent(){return this.content.filter(e=>e.type==="text").map(e=>e.content).join(`
73
- `)}},fO={[Bo.type]:Bo,[Tr.type]:Tr,[Vo.type]:Vo,[Kn.type]:Kn,[ko.type]:ko,[Po.type]:Po,[Ir.type]:Ir,[Mr.type]:Mr,[jo.type]:jo,[Si.type]:Si,[Fo.type]:Fo,[Ti.type]:Ti,[Lo.type]:Lo};function Nw(n){let e=fO[n.type];return e?new e(n):void 0}var Cn=class n{clientId;http=p($c);constructor(){this.clientId=this.getOrCreateClientId()}getOrCreateClientId(){let t=new URLSearchParams(window.location.search).get("clientId");if(!t){t=Math.random().toString(36).substring(2,15);let r=new URL(window.location.href);r.searchParams.set("clientId",t),window.history.pushState({},"",r)}return t}getClientId(){return this.clientId}sendEvent(e){return this.http.post(`/api/message?clientId=${this.clientId}`,e,{observe:"response",responseType:"text"}).pipe(ge(t=>{t.status!==200&&console.warn("[API] Unexpected status:",t.status)}),j(t=>t.body))}stopExecution(){return this.http.post(`/api/stop?clientId=${this.clientId}`,{})}getEventDetails(e){return this.http.get(`/api/event/${e}?clientId=${this.clientId}`,{responseType:"text"})}getEventsUrl(){return`/events?clientId=${this.clientId}`}getSessionState(){return this.http.get(`/api/session/state?clientId=${this.clientId}`).pipe(ge(e=>console.log("[API] Session state received:",e)))}deleteMessage(e){let t=`/api/thread/message/${encodeURIComponent(e)}?clientId=${this.clientId}`;return this.http.delete(t).pipe(ge(r=>console.log("[API] Delete message response:",r)))}static \u0275fac=function(t){return new(t||n)};static \u0275prov=C({token:n,factory:n.\u0275fac,providedIn:"root"})};var $o=class n{eventSource=null;eventsSubject=new H;connectionStatusSubject=new V({connected:!1,reconnectAttempts:0,maxAttempts:3});reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=3;RECONNECT_DELAY=2e3;events$=this.eventsSubject.asObservable();connectionStatus$=this.connectionStatusSubject.asObservable();codayApi=p(Cn);ngZone=p(me);connect(){console.log("[SSE] Setting up new EventSource"),this.eventSource&&(console.log("[SSE] Closing existing EventSource"),this.eventSource.close());let e=this.codayApi.getEventsUrl();this.eventSource=new EventSource(e),this.eventSource.onmessage=t=>{this.ngZone.run(()=>{console.log("[SSE] Message received:",t.data.substring(0,100)),this.reconnectAttempts=0,this.updateConnectionStatus(!0,0);try{let r=JSON.parse(t.data),i=Nw(r);i?(console.log("[SSE] Event:",i.type),this.eventsSubject.next(i)):console.warn("[SSE] Failed to build event:",r.type)}catch(r){console.error("[SSE] Parse error:",r.message)}})},this.eventSource.onopen=()=>{this.ngZone.run(()=>{console.log("[SSE] Connection established"),this.reconnectAttempts=0,this.updateConnectionStatus(!0,0)})},this.eventSource.onerror=t=>{this.ngZone.run(()=>{console.log("[SSE] EventSource error:",t),this.eventSource?.readyState===EventSource.CLOSED&&(console.log("[SSE] Connection closed"),this.updateConnectionStatus(!1,this.reconnectAttempts),this.reconnectAttempts<this.MAX_RECONNECT_ATTEMPTS?(console.log(`[SSE] Attempting reconnect ${this.reconnectAttempts+1}/${this.MAX_RECONNECT_ATTEMPTS}`),this.eventsSubject.next(new Kn({error:new Error(`Connection lost. Attempting to reconnect (${this.reconnectAttempts+1}/${this.MAX_RECONNECT_ATTEMPTS})...`)})),setTimeout(()=>{this.reconnectAttempts++,this.connect()},this.RECONNECT_DELAY)):(console.log("[SSE] Max reconnection attempts reached"),this.eventsSubject.next(new Kn({error:new Error("Connection lost permanently. Please refresh the page.")}))))})}}disconnect(){this.eventSource&&(console.log("[SSE] Disconnecting EventSource"),this.eventSource.close(),this.eventSource=null,this.updateConnectionStatus(!1,0))}isConnected(){return this.connectionStatusSubject.value.connected}updateConnectionStatus(e,t){this.connectionStatusSubject.next({connected:e,reconnectAttempts:t,maxAttempts:this.MAX_RECONNECT_ATTEMPTS})}ngOnDestroy(){this.disconnect(),this.eventsSubject.complete(),this.connectionStatusSubject.complete()}static \u0275fac=function(t){return new(t||n)};static \u0275prov=C({token:n,factory:n.\u0275fac,providedIn:"root"})};var ft=class n{destroy$=new H;messagesSubject=new V([]);isThinkingSubject=new V(!1);currentChoiceSubject=new V(null);projectTitleSubject=new V("Coday");currentInviteEventSubject=new V(null);messageToRestoreSubject=new V("");currentChoiceEvent=null;thinkingTimeout=null;messages$=this.messagesSubject.asObservable();isThinking$=this.isThinkingSubject.asObservable();currentChoice$=this.currentChoiceSubject.asObservable();projectTitle$=this.projectTitleSubject.asObservable();currentInviteEvent$=this.currentInviteEventSubject.asObservable();messageToRestore$=this.messageToRestoreSubject.asObservable();connectionStatus$;tabTitleService=null;codayApi=p(Cn);eventStream=p($o);constructor(){this.connectionStatus$=this.eventStream.connectionStatus$,this.initializeEventHandling()}setTabTitleService(e){this.tabTitleService=e}start(){this.eventStream.connect()}stop(){this.codayApi.stopExecution().subscribe({next:()=>console.log("[CODAY] Stop signal sent"),error:e=>console.error("[CODAY] Error stopping:",e)})}resetMessages(){console.log("[CODAY] Resetting messages for context change"),this.messagesSubject.next([]),this.currentChoiceSubject.next(null),this.currentInviteEventSubject.next(null),this.currentChoiceEvent=null,this.stopThinking()}sendMessage(e){let t=this.currentInviteEventSubject.value;if(t){let r=t.buildAnswer(e);this.currentInviteEventSubject.next(null),this.codayApi.sendEvent(r).subscribe({error:i=>console.error("[CODAY] Send error:",i)})}else{let r=new Tr({answer:e});this.codayApi.sendEvent(r).subscribe({error:i=>console.error("[CODAY] Send error:",i)})}}sendChoice(e){if(this.currentChoiceEvent){let t=this.currentChoiceEvent.buildAnswer(e);this.codayApi.sendEvent(t).subscribe({next:()=>{this.currentChoiceSubject.next(null)},error:r=>console.error("[CODAY] Choice error:",r)})}else console.error("[CODAY] No choice event available")}deleteMessage(e){console.log("[CODAY] Deleting message:",e);let t=this.messagesSubject.value.find(i=>i.id===e),r=this.extractTextContentFromMessage(t);return this.codayApi.deleteMessage(e).pipe(ge(i=>{i.success?(console.log("[CODAY] Message deleted successfully, updating local messages"),this.removeMessagesFromIndex(e),r.trim()&&(console.log("[CODAY] Restoring deleted message content to textarea"),this.messageToRestoreSubject.next(r))):console.warn("[CODAY] Failed to delete message:",i.error)}))}getCurrentMessages(){return this.messagesSubject.value}getCurrentProjectTitle(){return this.projectTitleSubject.value}getCurrentInviteEvent(){return this.currentInviteEventSubject.value}initializeEventHandling(){this.eventStream.events$.pipe(K(this.destroy$)).subscribe({next:e=>this.handleEvent(e),error:e=>console.error("[CODAY] Event stream error:",e),complete:()=>console.log("[CODAY] Event stream completed")})}handleEvent(e){e instanceof Bo?this.handleMessageEvent(e):e instanceof Fo?this.handleTextEvent(e):e instanceof Tr?this.handleAnswerEvent(e):e instanceof Kn?this.handleErrorEvent(e):e instanceof Lo?this.handleWarnEvent(e):e instanceof Ti?this.handleThinkingEvent(e):e instanceof jo?this.handleToolRequestEvent(e):e instanceof Si?this.handleToolResponseEvent(e):e instanceof Vo?this.handleChoiceEvent(e):e instanceof Ir?this.handleProjectSelectedEvent(e):e instanceof Mr?this.handleThreadSelectedEvent(e):e instanceof ko?this.handleHeartBeatEvent(e):e instanceof Po?this.handleInviteEvent(e):console.warn("[CODAY] Unhandled event type:",e.type)}handleMessageEvent(e){let t={id:e.timestamp,role:e.role,speaker:e.name,content:e.content,timestamp:new Date,type:"text"};this.addMessage(t)}handleTextEvent(e){let t={id:e.timestamp,role:e.speaker?"assistant":"system",speaker:e.speaker||"System",content:[{type:"text",content:e.text}],timestamp:new Date,type:e.speaker?"text":"technical"};this.addMessage(t)}handleAnswerEvent(e){let t={id:e.timestamp,role:"user",speaker:"User",content:[{type:"text",content:e.answer}],timestamp:new Date,type:"text"};this.addMessage(t)}handleErrorEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:`Error: ${JSON.stringify(e.error)}`}],timestamp:new Date,type:"error"};this.addMessage(t)}handleWarnEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:`Warning: ${JSON.stringify(e.warning)}`}],timestamp:new Date,type:"warning"};this.addMessage(t)}handleThinkingEvent(e){this.clearThinkingTimeout(),this.isThinkingSubject.next(!0),this.tabTitleService?.setSystemActive(),this.thinkingTimeout=setTimeout(()=>{this.isThinkingSubject.next(!1),this.thinkingTimeout=null,this.tabTitleService?.setSystemInactive()},Ti.debounce+1e3)}handleToolRequestEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:e.toSingleLineString()}],timestamp:new Date,type:"technical",eventId:e.timestamp};this.addMessage(t)}handleToolResponseEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:e.toSingleLineString()}],timestamp:new Date,type:"technical",eventId:e.timestamp};this.addMessage(t)}handleChoiceEvent(e){this.stopThinking(),this.currentChoiceEvent=e,this.tabTitleService?.setSystemInactive();let t=e.options.map(i=>({value:i,label:i})),r=e.optionalQuestion?`${e.optionalQuestion} ${e.invite}`:e.invite;this.currentChoiceSubject.next({options:t,label:r})}handleProjectSelectedEvent(e){console.log("[CODAY] Project selected:",e.projectName),this.resetMessages(),this.projectTitleSubject.next(e.projectName||"Coday")}handleThreadSelectedEvent(e){console.log("[CODAY] Thread selected:",e.threadId,e.threadName),this.resetMessages()}handleHeartBeatEvent(e){}handleInviteEvent(e){this.stopThinking(),this.currentInviteEventSubject.next(e),this.tabTitleService?.setSystemInactive()}addMessage(e){let r=[...this.messagesSubject.value,e];this.messagesSubject.next(r)}removeMessagesFromIndex(e){let t=this.messagesSubject.value,r=t.findIndex(o=>o.id===e);if(r===-1){console.warn("[CODAY] Message not found for local deletion:",e);return}if(r===0){console.warn("[CODAY] Cannot delete first message locally");return}let i=t.slice(0,r);console.log(`[CODAY] Locally removed ${t.length-i.length} messages from index ${r}`),this.messagesSubject.next(i),this.stopThinking()}extractTextContentFromMessage(e){return e?e.content.filter(t=>t.type==="text").map(t=>t.content).join(`
73
+ `)}},fO={[Bo.type]:Bo,[Tr.type]:Tr,[Vo.type]:Vo,[Kn.type]:Kn,[ko.type]:ko,[Po.type]:Po,[Ir.type]:Ir,[Mr.type]:Mr,[jo.type]:jo,[Si.type]:Si,[Fo.type]:Fo,[Ti.type]:Ti,[Lo.type]:Lo};function Nw(n){let e=fO[n.type];return e?new e(n):void 0}var Cn=class n{clientId;http=p($c);constructor(){this.clientId=this.getOrCreateClientId()}getOrCreateClientId(){let t=new URLSearchParams(window.location.search).get("clientId");if(!t){t=Math.random().toString(36).substring(2,15);let r=new URL(window.location.href);r.searchParams.set("clientId",t),window.history.pushState({},"",r)}return t}getClientId(){return this.clientId}sendEvent(e){return this.http.post(`/api/message?clientId=${this.clientId}`,e,{observe:"response",responseType:"text"}).pipe(ge(t=>{t.status!==200&&console.warn("[API] Unexpected status:",t.status)}),j(t=>t.body))}stopExecution(){return this.http.post(`/api/stop?clientId=${this.clientId}`,{})}getEventDetails(e){return this.http.get(`/api/event/${e}?clientId=${this.clientId}`,{responseType:"text"})}getEventsUrl(){return`/events?clientId=${this.clientId}`}getSessionState(){return this.http.get(`/api/session/state?clientId=${this.clientId}`).pipe(ge(e=>console.log("[API] Session state received:",e)))}deleteMessage(e){let t=`/api/thread/message/${encodeURIComponent(e)}?clientId=${this.clientId}`;return this.http.delete(t).pipe(ge(r=>console.log("[API] Delete message response:",r)))}static \u0275fac=function(t){return new(t||n)};static \u0275prov=C({token:n,factory:n.\u0275fac,providedIn:"root"})};var $o=class n{eventSource=null;eventsSubject=new H;connectionStatusSubject=new V({connected:!1,reconnectAttempts:0,maxAttempts:3});reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=3;RECONNECT_DELAY=2e3;events$=this.eventsSubject.asObservable();connectionStatus$=this.connectionStatusSubject.asObservable();codayApi=p(Cn);ngZone=p(me);connect(){console.log("[SSE] Setting up new EventSource"),this.eventSource&&(console.log("[SSE] Closing existing EventSource"),this.eventSource.close());let e=this.codayApi.getEventsUrl();this.eventSource=new EventSource(e),this.eventSource.onmessage=t=>{this.ngZone.run(()=>{console.log("[SSE] Message received:",t.data.substring(0,100)),this.reconnectAttempts=0,this.updateConnectionStatus(!0,0);try{let r=JSON.parse(t.data),i=Nw(r);i?(console.log("[SSE] Event:",i.type),this.eventsSubject.next(i)):console.warn("[SSE] Failed to build event:",r.type)}catch(r){console.error("[SSE] Parse error:",r.message)}})},this.eventSource.onopen=()=>{this.ngZone.run(()=>{console.log("[SSE] Connection established"),this.reconnectAttempts=0,this.updateConnectionStatus(!0,0)})},this.eventSource.onerror=t=>{this.ngZone.run(()=>{console.log("[SSE] EventSource error:",t),this.eventSource?.readyState===EventSource.CLOSED&&(console.log("[SSE] Connection closed"),this.updateConnectionStatus(!1,this.reconnectAttempts),this.reconnectAttempts<this.MAX_RECONNECT_ATTEMPTS?(console.log(`[SSE] Attempting reconnect ${this.reconnectAttempts+1}/${this.MAX_RECONNECT_ATTEMPTS}`),this.eventsSubject.next(new Kn({error:new Error(`Connection lost. Attempting to reconnect (${this.reconnectAttempts+1}/${this.MAX_RECONNECT_ATTEMPTS})...`)})),setTimeout(()=>{this.reconnectAttempts++,this.connect()},this.RECONNECT_DELAY)):(console.log("[SSE] Max reconnection attempts reached"),this.eventsSubject.next(new Kn({error:new Error("Connection lost permanently. Please refresh the page.")}))))})}}disconnect(){this.eventSource&&(console.log("[SSE] Disconnecting EventSource"),this.eventSource.close(),this.eventSource=null,this.updateConnectionStatus(!1,0))}isConnected(){return this.connectionStatusSubject.value.connected}updateConnectionStatus(e,t){this.connectionStatusSubject.next({connected:e,reconnectAttempts:t,maxAttempts:this.MAX_RECONNECT_ATTEMPTS})}ngOnDestroy(){this.disconnect(),this.eventsSubject.complete(),this.connectionStatusSubject.complete()}static \u0275fac=function(t){return new(t||n)};static \u0275prov=C({token:n,factory:n.\u0275fac,providedIn:"root"})};var ft=class n{destroy$=new H;messagesSubject=new V([]);isThinkingSubject=new V(!1);currentChoiceSubject=new V(null);projectTitleSubject=new V("Coday");currentInviteEventSubject=new V(null);messageToRestoreSubject=new V("");currentChoiceEvent=null;thinkingTimeout=null;messages$=this.messagesSubject.asObservable();isThinking$=this.isThinkingSubject.asObservable();currentChoice$=this.currentChoiceSubject.asObservable();projectTitle$=this.projectTitleSubject.asObservable();currentInviteEvent$=this.currentInviteEventSubject.asObservable();messageToRestore$=this.messageToRestoreSubject.asObservable();connectionStatus$;tabTitleService=null;codayApi=p(Cn);eventStream=p($o);constructor(){this.connectionStatus$=this.eventStream.connectionStatus$,this.initializeEventHandling()}setTabTitleService(e){this.tabTitleService=e}start(){this.eventStream.connect()}stop(){this.codayApi.stopExecution().subscribe({next:()=>console.log("[CODAY] Stop signal sent"),error:e=>console.error("[CODAY] Error stopping:",e)})}resetMessages(){console.log("[CODAY] Resetting messages for context change"),this.messagesSubject.next([]),this.currentChoiceSubject.next(null),this.currentInviteEventSubject.next(null),this.currentChoiceEvent=null,this.stopThinking()}sendMessage(e){let t=this.currentInviteEventSubject.value;if(t){let r=t.buildAnswer(e);this.currentInviteEventSubject.next(null),this.codayApi.sendEvent(r).subscribe({error:i=>console.error("[CODAY] Send error:",i)})}else{let r=new Tr({answer:e});this.codayApi.sendEvent(r).subscribe({error:i=>console.error("[CODAY] Send error:",i)})}}sendChoice(e){if(this.currentChoiceEvent){let t=this.currentChoiceEvent.buildAnswer(e);console.log("[CODAY-CHOICE] Choice sent successfully, clearing UI"),this.currentChoiceSubject.next(null),this.currentChoiceEvent=null,this.codayApi.sendEvent(t).subscribe({next:()=>{},error:r=>{console.error("[CODAY-CHOICE] Choice error:",r)}})}else console.error("[CODAY-CHOICE] No choice event available for choice:",e)}deleteMessage(e){console.log("[CODAY] Deleting message:",e);let t=this.messagesSubject.value.find(i=>i.id===e),r=this.extractTextContentFromMessage(t);return this.codayApi.deleteMessage(e).pipe(ge(i=>{i.success?(console.log("[CODAY] Message deleted successfully, updating local messages"),this.removeMessagesFromIndex(e),r.trim()&&(console.log("[CODAY] Restoring deleted message content to textarea"),this.messageToRestoreSubject.next(r))):console.warn("[CODAY] Failed to delete message:",i.error)}))}getCurrentMessages(){return this.messagesSubject.value}getCurrentProjectTitle(){return this.projectTitleSubject.value}getCurrentInviteEvent(){return this.currentInviteEventSubject.value}initializeEventHandling(){this.eventStream.events$.pipe(K(this.destroy$)).subscribe({next:e=>this.handleEvent(e),error:e=>console.error("[CODAY] Event stream error:",e),complete:()=>console.log("[CODAY] Event stream completed")})}handleEvent(e){e instanceof Bo?this.handleMessageEvent(e):e instanceof Fo?this.handleTextEvent(e):e instanceof Tr?this.handleAnswerEvent(e):e instanceof Kn?this.handleErrorEvent(e):e instanceof Lo?this.handleWarnEvent(e):e instanceof Ti?this.handleThinkingEvent(e):e instanceof jo?this.handleToolRequestEvent(e):e instanceof Si?this.handleToolResponseEvent(e):e instanceof Vo?this.handleChoiceEvent(e):e instanceof Ir?this.handleProjectSelectedEvent(e):e instanceof Mr?this.handleThreadSelectedEvent(e):e instanceof ko?this.handleHeartBeatEvent(e):e instanceof Po?this.handleInviteEvent(e):console.warn("[CODAY] Unhandled event type:",e.type)}handleMessageEvent(e){let t={id:e.timestamp,role:e.role,speaker:e.name,content:e.content,timestamp:new Date,type:"text"};this.addMessage(t)}handleTextEvent(e){let t={id:e.timestamp,role:e.speaker?"assistant":"system",speaker:e.speaker||"System",content:[{type:"text",content:e.text}],timestamp:new Date,type:e.speaker?"text":"technical"};this.addMessage(t)}handleAnswerEvent(e){let t={id:e.timestamp,role:"user",speaker:"User",content:[{type:"text",content:e.answer}],timestamp:new Date,type:"text"};this.addMessage(t)}handleErrorEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:`Error: ${JSON.stringify(e.error)}`}],timestamp:new Date,type:"error"};this.addMessage(t)}handleWarnEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:`Warning: ${JSON.stringify(e.warning)}`}],timestamp:new Date,type:"warning"};this.addMessage(t)}handleThinkingEvent(e){this.clearThinkingTimeout(),this.isThinkingSubject.next(!0),this.tabTitleService?.setSystemActive(),this.thinkingTimeout=setTimeout(()=>{this.isThinkingSubject.next(!1),this.thinkingTimeout=null,this.tabTitleService?.setSystemInactive()},Ti.debounce+1e3)}handleToolRequestEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:e.toSingleLineString()}],timestamp:new Date,type:"technical",eventId:e.timestamp};this.addMessage(t)}handleToolResponseEvent(e){let t={id:e.timestamp,role:"system",speaker:"System",content:[{type:"text",content:e.toSingleLineString()}],timestamp:new Date,type:"technical",eventId:e.timestamp};this.addMessage(t)}handleChoiceEvent(e){this.stopThinking(),this.currentChoiceEvent=e,this.tabTitleService?.setSystemInactive();let t=e.options.map(i=>({value:i,label:i})),r=e.optionalQuestion?`${e.optionalQuestion} ${e.invite}`:e.invite;this.currentChoiceSubject.next({options:t,label:r})}handleProjectSelectedEvent(e){console.log("[CODAY] Project selected:",e.projectName),this.resetMessages(),this.projectTitleSubject.next(e.projectName||"Coday")}handleThreadSelectedEvent(e){console.log("[CODAY] Thread selected:",e.threadId,e.threadName),this.resetMessages()}handleHeartBeatEvent(e){}handleInviteEvent(e){this.stopThinking(),this.currentInviteEventSubject.next(e),this.tabTitleService?.setSystemInactive()}addMessage(e){let r=[...this.messagesSubject.value,e];this.messagesSubject.next(r)}removeMessagesFromIndex(e){let t=this.messagesSubject.value,r=t.findIndex(o=>o.id===e);if(r===-1){console.warn("[CODAY] Message not found for local deletion:",e);return}if(r===0){console.warn("[CODAY] Cannot delete first message locally");return}let i=t.slice(0,r);console.log(`[CODAY] Locally removed ${t.length-i.length} messages from index ${r}`),this.messagesSubject.next(i),this.stopThinking()}extractTextContentFromMessage(e){return e?e.content.filter(t=>t.type==="text").map(t=>t.content).join(`
74
74
 
75
75
  `):""}clearThinkingTimeout(){this.thinkingTimeout&&(clearTimeout(this.thinkingTimeout),this.thinkingTimeout=null)}stopThinking(){this.clearThinkingTimeout(),this.isThinkingSubject.next(!1),this.tabTitleService&&this.tabTitleService.setSystemInactive()}ngOnDestroy(){this.clearThinkingTimeout(),this.destroy$.next(),this.destroy$.complete(),this.currentInviteEventSubject.complete(),this.messageToRestoreSubject.complete(),this.eventStream.disconnect()}static \u0275fac=function(t){return new(t||n)};static \u0275prov=C({token:n,factory:n.\u0275fac,providedIn:"root"})};function hO(n,e){if(n&1){let t=de();v(0,"app-chat-message",4),M("playRequested",function(i){S(t);let o=I();return T(o.onPlayMessage(i))})("copyRequested",function(i){S(t);let o=I();return T(o.onCopyMessage(i))})("deleteRequested",function(i){S(t);let o=I();return T(o.onDeleteMessage(i))}),m()}if(n&2){let t=e.$implicit,r=e.index,i=I();A("message",t)("canDelete",i.canDeleteMessage(r))}}function pO(n,e){if(n&1){let t=de();v(0,"div",5)(1,"div",6),ue(2,"span")(3,"span")(4,"span"),m(),v(5,"button",7),M("click",function(){S(t);let i=I();return T(i.onStop())}),R(6," Stop "),m()()}}function gO(n,e){if(n&1){let t=de();v(0,"button",8),M("click",function(){S(t);let i=I();return T(i.goToBottom())}),R(1," \u2193 "),m()}}var Wu=class n{messages=[];isThinking=!1;playRequested=new ne;copyRequested=new ne;stopRequested=new ne;lastMessageCount=0;destroy$=new H;isTracking=!0;showGoToBottom=!1;scrollContainer=null;lastScrollTop=0;NEAR_BOTTOM_THRESHOLD=100;scrollCheckTimeout;MESSAGE_FRESHNESS_THRESHOLD=5*60*1e3;elementRef=p(He);unreadService=p(Oo);voiceSynthesisService=p(Sr);preferencesService=p(Pt);codayService=p(ft);ngOnInit(){this.findScrollContainer(),this.setupFocusListeners()}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete(),this.scrollCheckTimeout&&clearTimeout(this.scrollCheckTimeout),window.removeEventListener("focus",this.handleWindowFocus),window.removeEventListener("blur",this.handleWindowBlur)}ngAfterViewChecked(){if(this.messages.length!==this.lastMessageCount){console.log("[CHAT-HISTORY] Message count changed:",this.lastMessageCount,"->",this.messages.length);let e=this.messages.length-this.lastMessageCount;e>0&&(this.handleNewMessages(e),this.handleVoiceAnnouncement(e)),this.lastMessageCount=this.messages.length,this.isTracking&&this.scrollToBottom()}this.scrollContainer||this.findScrollContainer()}scrollToBottom(){try{this.scrollContainer||this.findScrollContainer(),this.scrollContainer&&setTimeout(()=>{this.scrollContainer&&this.scrollContainer.scrollTo({top:this.scrollContainer.scrollHeight,behavior:"smooth"})},50)}catch(e){console.error("Error scrolling to bottom:",e)}}trackByMessageId(e,t){return t.id}onPlayMessage(e){this.playRequested.emit(e)}onCopyMessage(e){let t=e.content.filter(r=>r.type==="text").map(r=>r.content).join(`
76
76
 
package/package.json CHANGED
@@ -7,5 +7,5 @@
7
7
  "dependencies": {
8
8
  "sharp": "^0.33.5"
9
9
  },
10
- "version": "0.18.2"
10
+ "version": "0.18.4"
11
11
  }
package/server/server.js CHANGED
@@ -69190,6 +69190,9 @@ var AiThread = class _AiThread {
69190
69190
  parentThread;
69191
69191
  /** Internal storage of thread messages in chronological order */
69192
69192
  messages;
69193
+ get messagesLength() {
69194
+ return this.messages.length;
69195
+ }
69193
69196
  /**
69194
69197
  * Creates a new AiThread instance.
69195
69198
  * @param thread - Configuration object containing thread ID and optional message history
@@ -69223,21 +69226,16 @@ var AiThread = class _AiThread {
69223
69226
  if (!this.messages || !Array.isArray(this.messages)) {
69224
69227
  this.messages = [];
69225
69228
  }
69226
- if (!maxChars) return { messages: [...this.messages], compacted: false };
69227
- let { messages, overflow } = partition(this.messages.toReversed(), maxChars);
69228
- messages = messages.toReversed();
69229
- overflow = overflow.toReversed();
69230
- const messageIds = new Set(messages.map((m2) => m2.timestamp));
69231
- for (let i2 = 0; i2 < messages.length; i2++) {
69232
- const message = messages[i2];
69233
- if (message instanceof ToolResponseEvent && !messageIds.has(message.parentKey ?? "no_parent_key")) {
69234
- messages.splice(i2, 1);
69235
- overflow.push(message);
69236
- }
69229
+ if (!maxChars) {
69230
+ const cleanedMessages2 = this.cleanToolRequestResponseConsistency([...this.messages]);
69231
+ return { messages: cleanedMessages2, compacted: false };
69237
69232
  }
69233
+ let { messages, overflow } = partition(this.messages.toReversed(), maxChars);
69234
+ messages = this.cleanToolRequestResponseConsistency(messages.toReversed());
69235
+ overflow = this.cleanToolRequestResponseConsistency(overflow.toReversed());
69238
69236
  if (!compactor) {
69239
- this.messages = messages;
69240
- return { messages, compacted: true };
69237
+ this.messages = this.cleanToolRequestResponseConsistency(messages);
69238
+ return { messages: this.messages, compacted: true };
69241
69239
  }
69242
69240
  let summary;
69243
69241
  while (overflow.length) {
@@ -69245,12 +69243,54 @@ var AiThread = class _AiThread {
69245
69243
  summary = await compactor(overflowPartition.messages);
69246
69244
  overflow = overflowPartition.overflow.length ? [summary, ...overflowPartition.overflow] : [];
69247
69245
  }
69248
- this.messages = summary ? [summary, ...messages] : messages;
69246
+ const cleanedMessages = this.cleanToolRequestResponseConsistency(messages);
69247
+ this.messages = summary ? [summary, ...cleanedMessages] : cleanedMessages;
69249
69248
  return {
69250
- messages,
69249
+ messages: cleanedMessages,
69251
69250
  compacted: true
69252
69251
  };
69253
69252
  }
69253
+ /**
69254
+ * Cleans tool request-response consistency to prevent API errors.
69255
+ * Removes orphaned tool requests/responses that would cause Anthropic API 400 errors.
69256
+ *
69257
+ * @param messages Array of messages to clean
69258
+ * @returns Cleaned array of messages
69259
+ * @private
69260
+ */
69261
+ cleanToolRequestResponseConsistency(messages) {
69262
+ const cleanedMessages = [];
69263
+ const toolRequestIds = /* @__PURE__ */ new Set();
69264
+ const toolResponseIds = /* @__PURE__ */ new Set();
69265
+ for (const message of messages) {
69266
+ if (message instanceof ToolRequestEvent && message.toolRequestId) {
69267
+ toolRequestIds.add(message.toolRequestId);
69268
+ } else if (message instanceof ToolResponseEvent && message.toolRequestId) {
69269
+ toolResponseIds.add(message.toolRequestId);
69270
+ }
69271
+ }
69272
+ for (const message of messages) {
69273
+ let shouldKeep = true;
69274
+ if (message instanceof ToolRequestEvent) {
69275
+ if (message.toolRequestId && !toolResponseIds.has(message.toolRequestId)) {
69276
+ console.debug(`[AiThread] Removing orphaned tool request: ${message.name} (ID: ${message.toolRequestId})`);
69277
+ shouldKeep = false;
69278
+ }
69279
+ } else if (message instanceof ToolResponseEvent) {
69280
+ if (!message.toolRequestId) {
69281
+ console.warn(`[AiThread] Removing tool response without tool reference (timestamp: ${message.timestamp})`);
69282
+ shouldKeep = false;
69283
+ } else if (!toolRequestIds.has(message.toolRequestId)) {
69284
+ console.debug(`[AiThread] Removing orphaned tool response for missing request ID: ${message.toolRequestId}`);
69285
+ shouldKeep = false;
69286
+ }
69287
+ }
69288
+ if (shouldKeep) {
69289
+ cleanedMessages.push(message);
69290
+ }
69291
+ }
69292
+ return cleanedMessages;
69293
+ }
69254
69294
  /**
69255
69295
  * Resets the counters related to the run (all except price.thread)
69256
69296
  */
@@ -69625,7 +69665,8 @@ var AiThreadService = class {
69625
69665
  }
69626
69666
  async autoSave(newName) {
69627
69667
  const thread = this.activeThread$.value;
69628
- if (!thread) {
69668
+ if (!thread || thread.messagesLength == 0) {
69669
+ console.error(`Autosave of an empty or falsy thread aborted, threadId: ${thread?.id}`);
69629
69670
  return;
69630
69671
  }
69631
69672
  if (newName) {
@@ -97743,7 +97784,7 @@ var OPENAI_DEFAULT_MODELS = [
97743
97784
  }
97744
97785
  }
97745
97786
  ];
97746
- var OpenaiClient = class extends AiClient {
97787
+ var OpenaiClient = class _OpenaiClient extends AiClient {
97747
97788
  constructor(interactor, aiProviderConfig, logger2) {
97748
97789
  super(aiProviderConfig, logger2);
97749
97790
  this.interactor = interactor;
@@ -97754,6 +97795,19 @@ var OpenaiClient = class extends AiClient {
97754
97795
  this.name = aiProviderConfig.name;
97755
97796
  }
97756
97797
  name;
97798
+ static MAX_TOOLS = 128;
97799
+ /**
97800
+ * Truncates the tools list to OpenAI's maximum of 128 tools and warns the user if truncation occurs
97801
+ */
97802
+ truncateToolsIfNeeded(tools) {
97803
+ if (tools.length <= _OpenaiClient.MAX_TOOLS) {
97804
+ return tools;
97805
+ }
97806
+ this.interactor.warn(
97807
+ `\u26A0\uFE0F OpenAI limits tools to ${_OpenaiClient.MAX_TOOLS} maximum. Your agent has ${tools.length} tools. Truncating to first ${_OpenaiClient.MAX_TOOLS} tools. Consider reducing your integrations or using a shorter tool list for better performance.`
97808
+ );
97809
+ return tools.slice(0, _OpenaiClient.MAX_TOOLS);
97810
+ }
97757
97811
  async run(agent, thread) {
97758
97812
  thread.resetUsageForRun();
97759
97813
  const openai = this.isOpenaiReady();
@@ -97810,7 +97864,7 @@ var OpenaiClient = class extends AiClient {
97810
97864
  async processAssistantThread(client, agent, model, thread, subscriber) {
97811
97865
  const assistantStream = client.beta.threads.runs.stream(thread.data.openai.assistantThreadData.threadId, {
97812
97866
  assistant_id: agent.definition.openaiAssistantId,
97813
- tools: [...agent.tools.getTools(), { type: "file_search" }],
97867
+ tools: this.truncateToolsIfNeeded([...agent.tools.getTools(), { type: "file_search" }]),
97814
97868
  tool_choice: "auto",
97815
97869
  max_completion_tokens: 12e4,
97816
97870
  max_prompt_tokens: 12e4,
@@ -97826,7 +97880,7 @@ var OpenaiClient = class extends AiClient {
97826
97880
  const response = await client.chat.completions.create({
97827
97881
  model: model.name,
97828
97882
  messages: this.toOpenAiMessage(agent, data.messages),
97829
- tools: agent.tools.getTools(),
97883
+ tools: this.truncateToolsIfNeeded(agent.tools.getTools()),
97830
97884
  max_completion_tokens: void 0,
97831
97885
  temperature: agent.definition.temperature ?? 0.8
97832
97886
  });
@@ -102047,7 +102101,7 @@ var { HUMAN_PROMPT, AI_PROMPT } = Anthropic;
102047
102101
  var import_rxjs10 = __toESM(require_cjs(), 1);
102048
102102
  var ANTHROPIC_DEFAULT_MODELS = [
102049
102103
  {
102050
- name: "claude-sonnet-4-20250514",
102104
+ name: "claude-sonnet-4-5-20250929",
102051
102105
  alias: "BIG",
102052
102106
  contextWindow: 2e5,
102053
102107
  price: {
@@ -114756,7 +114810,7 @@ ${agentNames.join("\n")}`);
114756
114810
  return void 0;
114757
114811
  }
114758
114812
  async findAgentByNameStart(nameStart, context) {
114759
- if (!nameStart || context.oneshot) {
114813
+ if (!nameStart) {
114760
114814
  return;
114761
114815
  }
114762
114816
  await this.initialize(context);
@@ -114769,6 +114823,9 @@ ${agentNames.join("\n")}`);
114769
114823
  }
114770
114824
  const options = matchingAgents.map((agent) => agent.name);
114771
114825
  try {
114826
+ if (context.oneshot) {
114827
+ throw new Error("Agent ambiguous names not allowed in oneshot context");
114828
+ }
114772
114829
  const selection = await this.interactor.chooseOption(
114773
114830
  options,
114774
114831
  `Multiple agents match '${nameStart}', please select one:`
@@ -115266,7 +115323,9 @@ var Coday = class {
115266
115323
  continue;
115267
115324
  }
115268
115325
  const thread = this.context?.aiThread;
115269
- if (thread) thread.runStatus = "RUNNING" /* RUNNING */;
115326
+ if (thread) {
115327
+ thread.runStatus = "RUNNING" /* RUNNING */;
115328
+ }
115270
115329
  this.context?.addCommands(userCommand);
115271
115330
  try {
115272
115331
  this.context = await this.handlerLooper?.handle(this.context) ?? null;
@@ -122028,11 +122087,13 @@ app.post("/api/webhook/:uuid", async (req, res) => {
122028
122087
  try {
122029
122088
  const { uuid } = req.params;
122030
122089
  if (!uuid) {
122090
+ debugLog("WEBHOOK", "Missing UUID in request");
122031
122091
  res.status(400).send({ error: "Missing webhook UUID in URL" });
122032
122092
  return;
122033
122093
  }
122034
122094
  const webhook = await webhookService.get(uuid);
122035
122095
  if (!webhook) {
122096
+ debugLog("WEBHOOK", `Webhook not found for UUID: ${uuid}`);
122036
122097
  res.status(404).send({ error: `Webhook with UUID '${uuid}' not found` });
122037
122098
  return;
122038
122099
  }
@@ -122072,28 +122133,30 @@ app.post("/api/webhook/:uuid", async (req, res) => {
122072
122133
  return;
122073
122134
  }
122074
122135
  clientId = `webhook_${Math.random().toString(36).substring(2, 15)}`;
122136
+ const finalPrompts = title ? [`thread save ${title}`, ...prompts] : prompts;
122075
122137
  const oneShotOptions = {
122076
122138
  ...codayOptions,
122077
122139
  oneshot: true,
122078
122140
  // Creates isolated instance that terminates after processing
122079
122141
  project,
122080
122142
  // Target project for the AI agent interaction
122081
- prompts: title ? [`thread save ${title}`, ...prompts] : prompts
122143
+ prompts: finalPrompts
122082
122144
  // Auto-save thread with title + user prompts
122083
122145
  };
122084
122146
  const client = clientManager.getOrCreate(clientId, null, oneShotOptions, username);
122085
122147
  const interactor = client.getInteractor();
122086
122148
  client.startCoday();
122087
- logger.logWebhook({
122149
+ const logData = {
122088
122150
  project,
122089
122151
  title: title || "Untitled",
122090
122152
  username,
122091
122153
  clientId,
122092
- promptCount: prompts.length,
122154
+ promptCount: finalPrompts.length,
122093
122155
  awaitFinalAnswer: !!awaitFinalAnswer,
122094
122156
  webhookName: webhook.name,
122095
122157
  webhookUuid: webhook.uuid
122096
- });
122158
+ };
122159
+ logger.logWebhook(logData);
122097
122160
  const threadIdSource = client.getThreadId();
122098
122161
  if (awaitFinalAnswer) {
122099
122162
  const lastEventObservable = interactor.events.pipe(