@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-
|
|
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
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)
|
|
69227
|
-
|
|
69228
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
|
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)
|
|
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:
|
|
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
|
-
|
|
122149
|
+
const logData = {
|
|
122088
122150
|
project,
|
|
122089
122151
|
title: title || "Untitled",
|
|
122090
122152
|
username,
|
|
122091
122153
|
clientId,
|
|
122092
|
-
promptCount:
|
|
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(
|