worksona-js 0.2.0
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/LICENSE +21 -0
- package/README.md +296 -0
- package/agents/interviewer-agent.json +24 -0
- package/agents/legal-agent.json +24 -0
- package/agents/marketing-agent.json +24 -0
- package/agents/prd-editor-agent.json +21 -0
- package/agents/research-analyst.json +24 -0
- package/package.json +82 -0
- package/worksona.d.ts +147 -0
- package/worksona.js +2241 -0
- package/worksona.min.js +1 -0
package/worksona.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";class Agent{constructor(n){this.id=n.id,this.name=n.name,this.description=n.description,n.config?(this.config={...n,...n.config},delete this.config.config):this.config=n,this.systemPrompt=this.config.systemPrompt,this.examples=this.config.examples||[],this.config.traits&&(this.traits=this.config.traits),this.transactions=[],this.metrics={totalQueries:0,avgResponseTime:0,lastActive:null,successRate:1,errorCount:0},this.state={isActive:!0,currentProvider:this.config.provider||"openai",currentModel:this.config.model,lastError:null}}addTransaction(n){if(this.transactions.push(n),this.metrics.totalQueries++,this.metrics.lastActive=new Date,n.duration){const e=this.metrics.avgResponseTime*(this.metrics.totalQueries-1)+n.duration;this.metrics.avgResponseTime=e/this.metrics.totalQueries}n.error&&(this.metrics.errorCount++,this.metrics.successRate=(this.metrics.totalQueries-this.metrics.errorCount)/this.metrics.totalQueries,this.state.lastError=n.error),this.transactions.length>100&&(this.transactions=this.transactions.slice(-100))}getHistory(){return this.transactions}getMetrics(){return this.metrics}getState(){return this.state}}!function(n){class e{constructor(n={}){this.options={debug:!1,defaultProvider:"openai",defaultModel:"gpt-3.5-turbo",apiKeys:{},...n},this.agents=new Map,this.activeProvider=null,this.controlPanelId=null,this.eventHandlers={},this._initializeProviders(),!1!==n.controlPanel&&this.createFloatingControlPanel()}_initializeProviders(){this.providers={openai:this.options.apiKeys.openai?{chat:async(n,e)=>{try{const t=e.content&&"image"===e.content.type,o=(n.config.model||this.options.defaultModel||"gpt-4o").trim();let a;if(this._log(`Making OpenAI request with model: ${o}`,"info"),t||e&&"image"===e.type||e&&e.content&&"object"==typeof e.content&&"image"===e.content.type){let o;if(t?o=e.content:"image"===e.type?o=e:e.content&&"image"===e.content.type&&(o=e.content),!o||!o.imageUrl)throw new Error("Invalid image data: Missing required imageUrl property");a=[{role:"system",content:n.config.systemPrompt||"You are a helpful vision analysis assistant."},{role:"user",content:[{type:"text",text:o.prompt||"Please analyze this image."},{type:"image_url",image_url:{url:o.imageUrl,detail:o.detail||"high"}}]}],this._log(`Vision message structure: ${JSON.stringify(a)}`,"info")}else{let t="";if("string"==typeof e)t=e;else if(e&&"string"==typeof e.content)t=e.content;else if(e&&e.content)try{t=JSON.stringify(e.content)}catch(n){t="Unable to process message content"}else if(e)try{t=JSON.stringify(e)}catch(n){t="Unable to process message"}else t="No message provided";this._log(`Processed user content: ${t.substring(0,100)}${t.length>100?"...":""}`,"info"),a=[{role:"system",content:n.config.systemPrompt||"You are a helpful assistant."},...(n.config.examples||[]).flatMap(n=>[{role:"user",content:n.user},{role:"assistant",content:n.assistant}]),{role:"user",content:t}]}const s={model:o,messages:a,temperature:n.config.temperature||.7,max_tokens:n.config.maxTokens||500,top_p:n.config.topP||1,frequency_penalty:n.config.frequencyPenalty||0,presence_penalty:n.config.presencePenalty||0,stream:!1},r="https://api.openai.com/v1/chat/completions",i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKeys.openai}`,"OpenAI-Organization":n.config.organization||""},body:JSON.stringify(s)}),l=await i.json();if(!i.ok)throw this._log(`OpenAI API error: ${JSON.stringify(l)}`,"error"),new Error(l.error?.message||`OpenAI API error: ${i.status}`);return t&&this._log(`Successfully processed vision request with model: ${o}`),l.choices[0].message.content}catch(n){this._log(`OpenAI error details: ${n.message}`,"error"),this._handleError(n,"PROVIDER_ERROR","OpenAI request failed")}},defaultModels:{chat:"gpt-4o",vision:"gpt-4o"}}:null,anthropic:this.options.apiKeys.anthropic?{chat:async(n,e)=>{try{const t=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.options.apiKeys.anthropic,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:n.config.model||"claude-3-opus-20240229",max_tokens:n.config.maxTokens||500,temperature:n.config.temperature||.7,system:n.config.systemPrompt,messages:[...(n.config.examples||[]).flatMap(n=>[{role:"user",content:n.user},{role:"assistant",content:n.assistant}]),{role:"user",content:e}],top_p:n.config.topP||1,top_k:n.config.topK||50,metadata:{user_id:n.id}})}),o=await t.json();if(!t.ok)throw new Error(o.error?.message||"Anthropic API error");return o.content[0].text}catch(n){this._handleError(n,"PROVIDER_ERROR","Anthropic request failed")}},defaultModels:{chat:"claude-3-opus-20240229",completion:"claude-3-sonnet-20240229"}}:null,google:this.options.apiKeys.google?{chat:async(n,e)=>{try{const t=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${n.config.model||"gemini-pro"}:generateContent?key=${this.options.apiKeys.google}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({contents:[{role:"user",parts:[{text:n.config.systemPrompt}]},...(n.config.examples||[]).flatMap(n=>[{role:"user",parts:[{text:n.user}]},{role:"model",parts:[{text:n.assistant}]}]),{role:"user",parts:[{text:e}]}],generationConfig:{temperature:n.config.temperature||.7,maxOutputTokens:n.config.maxTokens||500,topP:n.config.topP||1,topK:n.config.topK||40,candidateCount:1},safetySettings:[{category:"HARM_CATEGORY_HARASSMENT",threshold:"BLOCK_MEDIUM_AND_ABOVE"},{category:"HARM_CATEGORY_HATE_SPEECH",threshold:"BLOCK_MEDIUM_AND_ABOVE"}]})}),o=await t.json();if(!t.ok)throw new Error(o.error?.message||"Google API error");return o.candidates[0].content.parts[0].text}catch(n){this._handleError(n,"PROVIDER_ERROR","Google request failed")}},defaultModels:{chat:"gemini-pro",vision:"gemini-pro-vision"}}:null}}_formatMessages(n,e,t){switch(n){case"openai":return[{role:"system",content:e.config.systemPrompt},...(e.config.examples||[]).flatMap(n=>[{role:"user",content:n.user},{role:"assistant",content:n.assistant}]),{role:"user",content:t}];case"anthropic":return[...(e.config.examples||[]).flatMap(n=>[{role:"user",content:n.user},{role:"assistant",content:n.assistant}]),{role:"user",content:t}];case"google":return[{role:"user",parts:[{text:e.config.systemPrompt}]},...(e.config.examples||[]).flatMap(n=>[{role:"user",parts:[{text:n.user}]},{role:"model",parts:[{text:n.assistant}]}]),{role:"user",parts:[{text:t}]}];default:throw new Error(`Unsupported provider: ${n}`)}}async loadAgent(n){if(!n.id||!n.name)return this._handleError(new Error("Invalid agent configuration"),"CONFIG_ERROR"),null;try{const e=new Agent(n);return this.agents.set(e.id,e),this._emit("agent-loaded",{agentId:e.id,name:e.name,description:e.description,provider:e.state.currentProvider,model:e.state.currentModel}),this.updateControlPanel(),this._log(`Agent loaded: ${e.name} (${e.id})`),e}catch(e){return this._handleError(e,"AGENT_LOAD_ERROR",`Failed to load agent: ${n.id}`),null}}async chat(n,e,t={}){const o=this.agents.get(n);if(!o)return this._handleError(new Error(`Agent not found: ${n}`),"AGENT_NOT_FOUND"),null;const a=o.config.provider||t.provider||this.options.defaultProvider;if(!this.providers[a])return this._handleError(new Error(`Provider not available: ${a}`),"PROVIDER_ERROR"),null;o.state.currentProvider=a,o.state.currentModel=o.config.model||this.options.defaultModel;const s={timestamp:new Date,query:e,response:null,duration:0,error:null,provider:a,model:o.state.currentModel};this._emit("chat-start",{agentId:n,message:e}),this._log(`Chat request to ${n}: ${e}`);const r=Date.now();try{const t=await this.providers[a].chat(o,e);return s.duration=Date.now()-r,s.response=t,o.addTransaction(s),this.updateControlPanel(),this._emit("chat-complete",{agentId:n,message:e,response:t,duration:s.duration}),this._log(`Chat response from ${n}: ${t}`),t}catch(e){return s.error=e,s.duration=Date.now()-r,o.addTransaction(s),this.updateControlPanel(),this._handleError(e,"CHAT_ERROR",`Chat failed with ${n}`),null}}getAgentHistory(n){const e=this.agents.get(n);return e?e.getHistory():[]}getAgentMetrics(n){const e=this.agents.get(n);return e?e.getMetrics():null}getAgentState(n){const e=this.agents.get(n);return e?e.getState():null}getAgent(n){return this.agents.get(n)}getAllAgents(){return Array.from(this.agents.values())}removeAgent(n){const e=this.agents.delete(n);return e&&(this._emit("agent-removed",n),this._log(`Agent removed: ${n}`),this.updateControlPanel()),e}on(n,e){this.eventHandlers[n]||(this.eventHandlers[n]=[]),this.eventHandlers[n].push(e)}off(n,e){this.eventHandlers[n]&&(this.eventHandlers[n]=this.eventHandlers[n].filter(n=>n!==e))}_emit(n,e){this.eventHandlers[n]&&this.eventHandlers[n].forEach(n=>n(e))}_handleError(n,e,t){let o=t||n.message;switch(e){case"IMAGE_PROCESSING_ERROR":n.message.includes("image_too_large")?o="Image size exceeds maximum allowed size. Please reduce the image size.":n.message.includes("invalid_image_format")?o="Invalid image format. Supported formats are: JPEG, PNG, WEBP, GIF.":n.message.includes("vision_model_unavailable")&&(o="Vision model is currently unavailable. Please try again later."),n.message.includes("invalid_api_key")?o="Invalid OpenAI API key. Please check your credentials.":n.message.includes("insufficient_quota")?o="OpenAI API quota exceeded. Please check your usage limits.":n.message.includes("rate_limit_exceeded")&&(o="OpenAI API rate limit exceeded. Please try again later.");break;case"PROVIDER_ERROR":n.message&&n.message.includes("401")?o="API key is invalid or missing. Please check your API key in the control panel.":n.message&&n.message.includes("invalid_api_key")?o="Invalid API key format. Please check your API key in the control panel.":n.message&&n.message.includes("model")&&(o=`Model error: ${n.message}. Please try a different model in the control panel.`);break;case"CONFIG_ERROR":o="Invalid agent configuration. Please check your agent configuration and try again.";break;case"AGENT_LOAD_ERROR":o=`Failed to load agent: ${n.message}. Please check the agent configuration and try again.`;break;case"AGENT_NOT_FOUND":o=`Agent not found: ${n.message}. Please check the agent ID and try again.`;break;case"CHAT_ERROR":o=`Chat failed with ${n.message}. Please check the chat request and try again.`;break;default:o=n.message||"An unknown error occurred. Please try again later."}const a={message:o,code:e,originalError:n};throw this._emit("error",a),this._log(`Error [${e}]: ${a.message}`,"error"),a}_log(n,e="info"){this.options.debug&&console[e](`[Worksona] ${n}`)}createControlPanel(n){this.controlPanelId=n;const e=document.getElementById(n);if(!e)return this._log("Control panel container not found","error"),!1;this.controlPanelContainer=e,e.innerHTML='\n <div class="worksona-control-panel">\n <div class="worksona-panel-header">\n <h2>Worksona Agents Control Panel</h2>\n <div class="worksona-header-buttons">\n <button class="worksona-expand-button" title="Toggle full screen">⛶</button>\n <button class="worksona-close-button">×</button>\n </div>\n </div>\n \n <div class="worksona-llm-status-bar">\n <div class="worksona-status-label">LLM Status</div>\n <div class="worksona-status-indicators">\n <div class="worksona-status-item">\n <div class="worksona-status-dot" id="worksona-openai-status"></div>\n <span>OpenAI</span>\n </div>\n <div class="worksona-status-item">\n <div class="worksona-status-dot" id="worksona-anthropic-status"></div>\n <span>Anthropic</span>\n </div>\n <div class="worksona-status-item">\n <div class="worksona-status-dot" id="worksona-google-status"></div>\n <span>Google</span>\n </div>\n </div>\n </div>\n \n <div class="worksona-tabs">\n <button class="worksona-tab" data-tab="api-keys">API Keys</button>\n <button class="worksona-tab active" data-tab="agents">Agents</button>\n </div>\n \n <div class="worksona-content">\n <div class="worksona-tab-content" id="worksona-api-keys-tab">\n <h3 class="worksona-section-title">LLM Provider API Keys</h3>\n \n <div class="worksona-key-input">\n <label for="worksona-openai-key">OpenAI API Key</label>\n <div class="worksona-input-group">\n <input type="password" id="worksona-openai-key" placeholder="sk-...">\n <button class="worksona-toggle-visibility">👁️</button>\n </div>\n </div>\n \n <div class="worksona-key-input">\n <label for="worksona-anthropic-key">Anthropic API Key</label>\n <div class="worksona-input-group">\n <input type="password" id="worksona-anthropic-key" placeholder="sk-ant-...">\n <button class="worksona-toggle-visibility">👁️</button>\n </div>\n </div>\n \n <div class="worksona-key-input">\n <label for="worksona-google-key">Google API Key</label>\n <div class="worksona-input-group">\n <input type="password" id="worksona-google-key" placeholder="AIza...">\n <button class="worksona-toggle-visibility">👁️</button>\n </div>\n </div>\n \n <div class="worksona-button-group">\n <button id="worksona-save-keys" class="worksona-primary-button">Save API Keys</button>\n <button id="worksona-test-connections" class="worksona-secondary-button">Test Connections</button>\n </div>\n </div>\n \n <div class="worksona-tab-content active" id="worksona-agents-tab">\n <div id="worksona-agent-list"></div>\n </div>\n </div>\n </div>\n ';const t=document.createElement("style");return t.textContent="\n .worksona-control-panel {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n color: #333;\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.15);\n overflow: hidden;\n width: 100%;\n max-width: 800px;\n margin: 0 auto;\n position: relative;\n }\n\n .worksona-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 15px 20px;\n border-bottom: 1px solid #eee;\n }\n\n .worksona-panel-header h2 {\n margin: 0;\n color: #1a56db;\n font-size: 18px;\n font-weight: 600;\n }\n\n .worksona-header-buttons {\n display: flex;\n gap: 10px;\n align-items: center;\n }\n\n .worksona-expand-button {\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #64748b;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.2s;\n }\n\n .worksona-expand-button:hover {\n color: #334155;\n }\n\n .worksona-llm-status-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 20px;\n background: #111827;\n color: white;\n }\n\n .worksona-status-indicators {\n display: flex;\n gap: 20px;\n }\n\n .worksona-status-item {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 14px;\n }\n\n .worksona-status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #6b7280;\n }\n\n .worksona-status-dot.active {\n background: #10b981;\n }\n\n .worksona-tabs {\n display: flex;\n padding: 0 20px;\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n }\n\n .worksona-tab {\n padding: 15px 20px;\n background: none;\n border: none;\n cursor: pointer;\n color: #6b7280;\n font-weight: 500;\n position: relative;\n }\n\n .worksona-tab:hover {\n color: #4b5563;\n }\n\n .worksona-tab.active {\n color: #2563eb;\n }\n\n .worksona-tab.active::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 2px;\n background: #2563eb;\n }\n\n .worksona-content {\n padding: 20px;\n }\n\n .worksona-tab-content {\n display: none;\n }\n\n .worksona-tab-content.active {\n display: block;\n }\n\n .worksona-section-title {\n font-size: 16px;\n font-weight: 600;\n margin-top: 0;\n margin-bottom: 20px;\n color: #111827;\n }\n\n .worksona-key-input {\n margin-bottom: 15px;\n }\n\n .worksona-key-input label {\n display: block;\n margin-bottom: 5px;\n font-weight: 500;\n color: #374151;\n }\n\n .worksona-input-group {\n display: flex;\n align-items: center;\n }\n\n .worksona-input-group input {\n flex: 1;\n padding: 10px 12px;\n border: 1px solid #d1d5db;\n border-radius: 6px 0 0 6px;\n font-size: 14px;\n }\n\n .worksona-toggle-visibility {\n padding: 10px 12px;\n background: #f9fafb;\n border: 1px solid #d1d5db;\n border-left: none;\n border-radius: 0 6px 6px 0;\n cursor: pointer;\n }\n\n .worksona-button-group {\n display: flex;\n gap: 10px;\n margin-top: 20px;\n }\n\n .worksona-primary-button {\n padding: 8px 16px;\n background: #2563eb;\n color: white;\n border: none;\n border-radius: 6px;\n font-weight: 500;\n cursor: pointer;\n }\n\n .worksona-primary-button:hover {\n background: #1d4ed8;\n }\n\n .worksona-secondary-button {\n padding: 8px 16px;\n background: #f3f4f6;\n color: #374151;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n font-weight: 500;\n cursor: pointer;\n }\n\n .worksona-secondary-button:hover {\n background: #e5e7eb;\n }\n\n .worksona-agent-card {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n padding: 15px;\n margin-bottom: 15px;\n transition: box-shadow 0.2s;\n }\n \n .worksona-agent-card:hover {\n box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n }\n\n .worksona-agent-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 10px;\n cursor: pointer;\n position: relative;\n }\n \n .worksona-expand-icon {\n font-size: 12px;\n color: #6b7280;\n transition: transform 0.2s;\n }\n \n .worksona-expand-icon.rotated {\n transform: rotate(180deg);\n }\n \n .worksona-agent-details.active + .worksona-expand-icon {\n transform: rotate(180deg);\n }\n\n .worksona-agent-name {\n font-size: 16px;\n font-weight: 600;\n color: #111827;\n margin: 0;\n }\n\n .worksona-agent-id {\n color: #6b7280;\n font-size: 12px;\n font-family: monospace;\n }\n \n .worksona-agent-status {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n \n .worksona-status-label {\n font-size: 12px;\n padding: 2px 6px;\n border-radius: 10px;\n background: #f3f4f6;\n }\n \n .worksona-agent-status.active .worksona-status-label {\n background: #dcfce7;\n color: #166534;\n }\n \n .worksona-agent-status.inactive .worksona-status-label {\n background: #fee2e2;\n color: #991b1b;\n }\n\n .worksona-agent-description {\n color: #4b5563;\n margin-bottom: 15px;\n font-size: 14px;\n }\n \n .worksona-agent-details {\n display: none;\n overflow: hidden;\n border-top: 1px solid #e5e7eb;\n margin-top: 10px;\n padding-top: 15px;\n }\n \n .worksona-agent-details.active {\n display: block;\n }\n \n .worksona-agent-tabs {\n display: flex;\n border-bottom: 1px solid #e5e7eb;\n margin-bottom: 15px;\n }\n \n .worksona-agent-tab {\n padding: 8px 16px;\n border: none;\n background: none;\n cursor: pointer;\n color: #6b7280;\n font-weight: 500;\n position: relative;\n font-size: 14px;\n }\n \n .worksona-agent-tab:hover {\n color: #111827;\n }\n \n .worksona-agent-tab.active {\n color: #2563eb;\n border-bottom: 2px solid #2563eb;\n }\n \n .worksona-agent-tab-content {\n display: none;\n }\n \n .worksona-agent-tab-content.active {\n display: block;\n }\n \n .worksona-agent-tab-content h4 {\n font-size: 14px;\n font-weight: 600;\n margin: 0 0 10px;\n color: #111827;\n }\n \n .worksona-config-details,\n .worksona-traits,\n .worksona-metrics {\n background: #f9fafb;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 15px;\n font-size: 13px;\n line-height: 1.5;\n }\n \n .worksona-prompt-box {\n background: #f9fafb;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 15px;\n font-size: 13px;\n line-height: 1.5;\n white-space: pre-wrap;\n font-family: monospace;\n max-height: 200px;\n overflow-y: auto;\n }\n \n .worksona-examples {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-bottom: 20px;\n }\n \n .worksona-example {\n background: #f9fafb;\n border-radius: 6px;\n padding: 12px;\n font-size: 13px;\n }\n \n .worksona-example-user {\n margin-bottom: 8px;\n color: #4b5563;\n }\n \n .worksona-example-assistant {\n color: #1f2937;\n }\n \n .worksona-history {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-bottom: 15px;\n max-height: 300px;\n overflow-y: auto;\n }\n \n .worksona-history-item {\n background: #f9fafb;\n border-radius: 6px;\n padding: 12px;\n font-size: 13px;\n }\n \n .worksona-history-time {\n font-size: 11px;\n color: #6b7280;\n margin-bottom: 5px;\n }\n \n .worksona-history-query {\n margin-bottom: 8px;\n color: #4b5563;\n }\n \n .worksona-history-response {\n color: #1f2937;\n margin-bottom: 8px;\n }\n \n .worksona-history-meta {\n font-size: 11px;\n color: #6b7280;\n }\n \n .worksona-no-agents {\n text-align: center;\n padding: 40px 20px;\n color: #6b7280;\n background: #f9fafb;\n border-radius: 8px;\n }\n \n .worksona-no-examples {\n color: #6b7280;\n font-style: italic;\n background: #f9fafb;\n padding: 12px;\n border-radius: 6px;\n margin: 10px 0;\n }\n \n .worksona-control-panel {\n box-shadow: 0 5px 20px rgba(0,0,0,0.2);\n max-height: 80vh;\n overflow: auto;\n background: white;\n border-radius: 8px;\n }\n \n .worksona-json-display {\n background: #f8fafc;\n border-radius: 6px;\n padding: 15px;\n margin: 0;\n font-family: monospace;\n font-size: 13px;\n line-height: 1.5;\n overflow: auto;\n max-height: 500px;\n white-space: pre-wrap;\n color: #334155;\n border: 1px solid #e2e8f0;\n }\n \n /* Ensure the json tab content has proper height */\n #worksona-agent-tab-content[id$=\"-json\"] {\n max-height: 500px;\n overflow: auto;\n }\n \n /* JSON syntax highlighting */\n .worksona-json-key {\n color: #0f766e;\n }\n \n .worksona-json-string {\n color: #b91c1c;\n }\n \n .worksona-json-number {\n color: #1d4ed8;\n }\n \n .worksona-json-boolean {\n color: #7e22ce;\n }\n \n .worksona-json-null {\n color: #64748b;\n }\n \n /* Ensure the modal is scrollable on smaller screens */\n @media (max-height: 768px) {\n #worksona-modal-container {\n max-height: 90vh;\n }\n \n .worksona-control-panel {\n max-height: 90vh;\n }\n }\n ",document.head.appendChild(t),this._setupEventListeners(e),this.updateControlPanel(),!0}_setupEventListeners(n){if(!(n=n||this.controlPanelContainer))return void this._log("No container available for event listeners","error");n.querySelectorAll(".worksona-tab").forEach(e=>{e.addEventListener("click",()=>{n.querySelectorAll(".worksona-tab").forEach(n=>n.classList.remove("active")),n.querySelectorAll(".worksona-tab-content").forEach(n=>n.classList.remove("active")),e.classList.add("active"),document.getElementById(`worksona-${e.dataset.tab}-tab`).classList.add("active")})}),n.querySelectorAll(".worksona-toggle-visibility").forEach(n=>{n.addEventListener("click",()=>{const e=n.previousElementSibling;"password"===e.type?(e.type="text",n.textContent="🔒"):(e.type="password",n.textContent="👁️")})});const e=document.getElementById("worksona-save-keys");if(e){const n=e.cloneNode(!0);e.parentNode.replaceChild(n,e),n.addEventListener("click",()=>{const n=document.getElementById("worksona-openai-key").value,e=document.getElementById("worksona-anthropic-key").value,t=document.getElementById("worksona-google-key").value;n&&localStorage.setItem("openai_api_key",n),e&&localStorage.setItem("anthropic_api_key",e),t&&localStorage.setItem("google_api_key",t),this.options.apiKeys={...this.options.apiKeys,...n&&{openai:n},...e&&{anthropic:e},...t&&{google:t}},this._initializeProviders(),this.updateControlPanel(),this._emit("api-keys-updated",{providers:Object.keys(this.options.apiKeys)}),alert("API keys saved successfully!")})}const t=document.getElementById("worksona-test-connections");if(t){const n=t.cloneNode(!0);t.parentNode.replaceChild(n,t),n.addEventListener("click",async()=>{n.disabled=!0,n.textContent="Testing...";try{await this._testProviderConnections(),this.updateControlPanel()}finally{n.disabled=!1,n.textContent="Test Connections"}})}const o=n.querySelector(".worksona-close-button");if(o){const e=o.cloneNode(!0);o.parentNode.replaceChild(e,o),e.addEventListener("click",()=>{const e=n.querySelector(".worksona-control-panel");e&&(e.style.display="none")})}n.querySelectorAll('input[type="range"]').forEach(n=>{const e=n.nextElementSibling;n.addEventListener("input",()=>{e&&(e.textContent=n.value)}),e&&n.value&&(e.textContent=n.value)})}async _testProviderConnections(){const n=["openai","anthropic","google"];for(const e of n){const n=document.getElementById(`worksona-${e}-status`);if(n)if(this.options.apiKeys[e]&&""!==this.options.apiKeys[e].trim())try{let t=!1;switch(e){case"openai":t=this.options.apiKeys.openai&&this.options.apiKeys.openai.startsWith("sk-");break;case"anthropic":t=this.options.apiKeys.anthropic&&this.options.apiKeys.anthropic.startsWith("sk-ant-");break;case"google":t=this.options.apiKeys.google&&this.options.apiKeys.google.length>10}n.className=t?"worksona-status-dot active":"worksona-status-dot",this._log(`Provider ${e} validation result: ${t?"valid":"invalid"}`)}catch(t){n.className="worksona-status-dot",console.error(`Error testing ${e} connection:`,t)}else n.className="worksona-status-dot"}}updateControlPanel(){this.controlPanelId&&(this._updateProviderStatus(),Object.entries(this.options.apiKeys).forEach(([n,e])=>{const t=document.getElementById(`worksona-${n}-key`);t&&e&&(t.value=e)}),this._updateAgentList(),this._setupAgentEventListeners(),this.controlPanelContainer&&this._setupEventListeners(this.controlPanelContainer))}_updateProviderStatus(){["openai","anthropic","google"].forEach(n=>{const e=document.getElementById(`worksona-${n}-status`);if(!e)return;const t=!!this.options.apiKeys[n];e.className=t?"worksona-status-dot active":"worksona-status-dot"})}_updateAgentList(){const n=document.getElementById("worksona-agent-list");if(!n)return;const e=this.getAgents();0!==e.length?(n.innerHTML=e.map(n=>{const e=n.getMetrics(),t=n.getState(),o=n.getHistory(),a=o.length>0?o.slice(-5).map(n=>`\n <div class="worksona-history-item">\n <div class="worksona-history-time">${new Date(n.timestamp).toLocaleTimeString()}</div>\n <div class="worksona-history-query"><strong>Query:</strong> ${this._escapeHtml(n.query)}</div>\n <div class="worksona-history-response"><strong>Response:</strong> ${this._escapeHtml(n.response||"Error: "+(n.error?.message||"Unknown error"))}</div>\n <div class="worksona-history-meta">\n <span>Provider: ${n.provider}</span> | \n <span>Model: ${n.model}</span> | \n <span>Duration: ${n.duration}ms</span>\n </div>\n </div>\n `).join(""):"<p>No interaction history available yet.</p>",s=n=>n.systemPrompt||n.config?.systemPrompt||n.config?.config?.systemPrompt||"",r=n=>{const e=n.examples||n.config?.examples||n.config?.config?.examples||[];return console.log("Agent:",n.id,"Examples:",JSON.stringify(e)),e},i=s(n),l=i?`<div class="worksona-prompt-box">${this._escapeHtml(i)}</div>`:'<p class="worksona-no-examples">No system prompt has been defined for this agent. A system prompt helps establish the agent\'s behavior and capabilities.</p>',d=r(n),c=d&&d.length>0?d.map(n=>`\n <div class="worksona-example">\n <div class="worksona-example-user"><strong>User:</strong> ${this._escapeHtml(n.user||"")}</div>\n <div class="worksona-example-assistant"><strong>Assistant:</strong> ${this._escapeHtml(n.assistant||"")}</div>\n </div>\n `).join(""):'<p class="worksona-no-examples">No examples have been defined for this agent. Examples help demonstrate the expected conversation flow.</p>',p=`\n <div class="worksona-config-details">\n <h4>Model Settings</h4>\n <div><strong>Provider:</strong> ${n.config?.provider||n.state?.currentProvider||"default"}</div>\n <div><strong>Model:</strong> ${n.config?.model||n.state?.currentModel||"default"}</div>\n <div><strong>Temperature:</strong> ${void 0!==n.config?.temperature?n.config.temperature:void 0!==n.config?.config?.temperature?n.config.config.temperature:"default"}</div>\n <div><strong>Max Tokens:</strong> ${void 0!==n.config?.maxTokens?n.config.maxTokens:void 0!==n.config?.config?.maxTokens?n.config.config.maxTokens:"default"}</div>\n ${void 0!==n.config?.topP||void 0!==n.config?.config?.topP?`<div><strong>Top P:</strong> ${void 0!==n.config?.topP?n.config.topP:n.config?.config?.topP}</div>`:""}\n ${void 0!==n.config?.frequencyPenalty||void 0!==n.config?.config?.frequencyPenalty?`<div><strong>Frequency Penalty:</strong> ${void 0!==n.config?.frequencyPenalty?n.config.frequencyPenalty:n.config?.config?.frequencyPenalty}</div>`:""}\n ${void 0!==n.config?.presencePenalty||void 0!==n.config?.config?.presencePenalty?`<div><strong>Presence Penalty:</strong> ${void 0!==n.config?.presencePenalty?n.config.presencePenalty:n.config?.config?.presencePenalty}</div>`:""}\n </div>\n `,g=JSON.stringify({id:n.id,name:n.name,description:n.description,config:{provider:n.config.provider,model:n.config.model,temperature:n.config.temperature,maxTokens:n.config.maxTokens,topP:n.config.topP,frequencyPenalty:n.config.frequencyPenalty,presencePenalty:n.config.presencePenalty},systemPrompt:s(n),examples:r(n),traits:n.traits||{},metrics:n.getMetrics(),state:n.getState(),transactions:n.getHistory().slice(-5)},null,2),u=n.traits||{},m=`\n <div class="worksona-traits">\n ${u.personality?`<div><strong>Personality:</strong> ${u.personality.join(", ")}</div>`:""}\n ${u.knowledge?`<div><strong>Knowledge:</strong> ${u.knowledge.join(", ")}</div>`:""}\n ${u.tone?`<div><strong>Tone:</strong> ${u.tone}</div>`:""}\n ${u.background?`<div><strong>Background:</strong> ${u.background}</div>`:""}\n </div>\n `;return`\n <div class="worksona-agent-card">\n <div class="worksona-agent-header" onclick="document.getElementById('worksona-agent-details-${n.id}').classList.toggle('active'); this.querySelector('.worksona-expand-icon').classList.toggle('rotated')">\n <h3 class="worksona-agent-name">${n.name}</h3>\n <div class="worksona-agent-status ${t.isActive?"active":"inactive"}">\n <span class="worksona-agent-id">${n.id}</span>\n <span class="worksona-status-label">${t.isActive?"Active":"Inactive"}</span>\n </div>\n <div class="worksona-expand-icon">▼</div>\n </div>\n <p class="worksona-agent-description">${n.description||"No description provided"}</p>\n \n <div id="worksona-agent-details-${n.id}" class="worksona-agent-details">\n <div class="worksona-agent-tabs">\n <button class="worksona-agent-tab active" data-agent="${n.id}" data-tab="agent">Agent Details</button>\n <button class="worksona-agent-tab" data-agent="${n.id}" data-tab="model">Model Settings</button>\n <button class="worksona-agent-tab" data-agent="${n.id}" data-tab="prompt">System Prompt</button>\n <button class="worksona-agent-tab" data-agent="${n.id}" data-tab="history">History</button>\n <button class="worksona-agent-tab" data-agent="${n.id}" data-tab="json">Raw JSON</button>\n </div>\n \n <div class="worksona-agent-tab-content active" id="worksona-agent-${n.id}-agent">\n <h4>Agent Configuration</h4>\n <div class="worksona-config-details">\n <div><strong>ID:</strong> ${n.id}</div>\n <div><strong>Name:</strong> ${n.name}</div>\n <div><strong>Description:</strong> ${n.description||"No description provided"}</div>\n </div>\n <h4>Traits</h4>\n ${m}\n </div>\n \n <div class="worksona-agent-tab-content" id="worksona-agent-${n.id}-model">\n <h4>Model Settings</h4>\n ${p}\n </div>\n \n <div class="worksona-agent-tab-content" id="worksona-agent-${n.id}-prompt">\n <h4>System Prompt</h4>\n ${l}\n \n <h4>Examples</h4>\n <div class="worksona-examples">\n ${c}\n </div>\n </div>\n \n <div class="worksona-agent-tab-content" id="worksona-agent-${n.id}-history">\n <h4>Recent Interactions</h4>\n <div class="worksona-history">\n ${a}\n </div>\n <div class="worksona-metrics">\n <div><strong>Total Queries:</strong> ${e.totalQueries}</div>\n <div><strong>Avg Response Time:</strong> ${Math.round(e.avgResponseTime)}ms</div>\n <div><strong>Success Rate:</strong> ${(100*e.successRate).toFixed(1)}%</div>\n <div><strong>Last Active:</strong> ${e.lastActive?new Date(e.lastActive).toLocaleTimeString():"Never"}</div>\n </div>\n </div>\n \n <div class="worksona-agent-tab-content" id="worksona-agent-${n.id}-json">\n <h4>Agent Configuration JSON</h4>\n <div class="worksona-json-display">${this._escapeHtml(g)}</div>\n </div>\n </div>\n </div>\n `}).join(""),this.agentTabEventListeners&&this.agentTabEventListeners.forEach(({element:n,type:e,listener:t})=>{n.removeEventListener(e,t)}),this.agentTabEventListeners=[],n.querySelectorAll(".worksona-agent-tab").forEach(n=>{const e=e=>{const t=n.dataset.agent,o=n.dataset.tab;document.querySelectorAll(`.worksona-agent-tab[data-agent="${t}"]`).forEach(n=>{n.classList.remove("active")}),document.querySelectorAll(`[id^="worksona-agent-${t}-"]`).forEach(n=>{n.classList.remove("active")}),n.classList.add("active"),document.getElementById(`worksona-agent-${t}-${o}`).classList.add("active")};this.agentTabEventListeners.push({element:n,type:"click",listener:e}),n.addEventListener("click",e)})):n.innerHTML='\n <div class="worksona-no-agents">\n <p>No agents have been loaded yet.</p>\n <p>Agents will appear here when they are loaded by your application.</p>\n </div>\n '}_escapeHtml(n){return n?n.toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"):""}_setupAgentEventListeners(){this.off("agent-loaded",this._handleAgentLoaded),this.off("agent-removed",this._handleAgentRemoved),this.on("agent-loaded",this._handleAgentLoaded.bind(this)),this.on("agent-removed",this._handleAgentRemoved.bind(this))}_handleAgentLoaded(){this._updateAgentList()}_handleAgentRemoved(){this._updateAgentList()}getAgents(){return Array.from(this.agents.values())}createFloatingControlPanel(){if(!document.body)return"loading"===document.readyState?void document.addEventListener("DOMContentLoaded",()=>this.createFloatingControlPanel()):void setTimeout(()=>this.createFloatingControlPanel(),100);try{const n=document.createElement("div");n.id="worksona-floating-control";const e=document.createElement("button");e.id="worksona-floating-button",e.innerHTML="⚙️",e.setAttribute("aria-label","Open Worksona Control Panel"),n.appendChild(e);const t=document.createElement("div");t.id="worksona-modal-container";const o=document.createElement("div");o.id="worksona-overlay",n.appendChild(o),n.appendChild(t),document.body.appendChild(n),setTimeout(()=>{this.createControlPanel("worksona-modal-container");t.querySelector(".worksona-control-panel")||(this._log("Failed to create control panel content, retrying...","warn"),setTimeout(()=>{this.createControlPanel("worksona-modal-container")},100))},10);const a=()=>{o.classList.remove("active"),t.classList.remove("active");const n=t.querySelector(".worksona-control-panel");n&&(n.style.display="none")},s=document.createElement("style");s.textContent="\n #worksona-floating-button {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 50px;\n height: 50px;\n border-radius: 50%;\n background: #2563eb;\n color: white;\n border: none;\n font-size: 24px;\n box-shadow: 0 2px 10px rgba(0,0,0,0.2);\n cursor: pointer;\n z-index: 9998;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease-in-out;\n }\n \n #worksona-floating-button:hover {\n transform: scale(1.1);\n background: #1d4ed8;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n #worksona-floating-button:active {\n transform: scale(0.95);\n }\n \n @media (max-width: 768px) {\n #worksona-floating-button {\n width: 45px;\n height: 45px;\n font-size: 20px;\n bottom: 15px;\n right: 15px;\n }\n }\n \n #worksona-modal-container {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 10000;\n width: 90%;\n max-width: 800px;\n max-height: 80vh;\n overflow: auto;\n display: none;\n background: white;\n border-radius: 8px;\n }\n \n #worksona-modal-container.active {\n display: block;\n }\n \n #worksona-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0,0,0,0.5);\n z-index: 9999;\n display: none;\n }\n \n #worksona-overlay.active {\n display: block;\n }\n \n .worksona-control-panel {\n box-shadow: 0 5px 20px rgba(0,0,0,0.2);\n max-height: 80vh;\n overflow: auto;\n background: white;\n border-radius: 8px;\n transition: all 0.3s ease;\n }\n\n .worksona-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 15px 20px;\n border-bottom: 1px solid #eee;\n background: #fff;\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n .worksona-header-buttons {\n display: flex;\n gap: 10px;\n align-items: center;\n }\n\n .worksona-expand-button {\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #64748b;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.2s;\n }\n\n .worksona-expand-button:hover {\n color: #334155;\n }\n\n .worksona-control-panel.expanded {\n position: fixed;\n top: 0;\n left: 0;\n width: 100% !important;\n height: 100vh !important;\n max-height: 100vh !important;\n max-width: 100% !important;\n border-radius: 0;\n z-index: 10001;\n }\n\n #worksona-modal-container.expanded {\n width: 100%;\n max-width: 100%;\n height: 100vh;\n max-height: 100vh;\n top: 0;\n left: 0;\n transform: none;\n border-radius: 0;\n }\n ",document.head.appendChild(s),e.addEventListener("click",()=>{o.classList.add("active"),t.classList.add("active");const n=t.querySelector(".worksona-control-panel");if(n)n.style.display="block";else{this._log("Control panel not found, attempting to recreate","warn");!1!==this.createControlPanel("worksona-modal-container")?setTimeout(()=>{const n=t.querySelector(".worksona-control-panel");n?(n.style.display="block",this._log("Control panel recreated successfully","info")):(this._log("Failed to recreate control panel - panel element not found after creation","error"),this.updateControlPanel())},50):this._log("Failed to recreate control panel - container not found","error")}});const r=t.querySelector(".worksona-expand-button");r&&r.addEventListener("click",()=>{const n=t.querySelector(".worksona-control-panel");n.classList.contains("expanded")?(n.classList.remove("expanded"),t.classList.remove("expanded"),r.innerHTML="⛶",r.title="Expand to full screen"):(n.classList.add("expanded"),t.classList.add("expanded"),r.innerHTML="⛾",r.title="Return to normal size")}),o.addEventListener("click",a);const i=t.querySelector(".worksona-close-button");i&&i.addEventListener("click",n=>{n.preventDefault(),n.stopPropagation(),a()}),document.addEventListener("keydown",n=>{"Escape"===n.key&&o.classList.contains("active")&&a()})}catch(n){this._log(`Error creating floating control panel: ${n.message}`,"error"),setTimeout(()=>this.createFloatingControlPanel(),1e3)}}isControlPanelReady(){const n=document.getElementById(this.controlPanelId),e=n?.querySelector(".worksona-control-panel");return!(!n||!e)}async processImage(n,e,t={}){const o=this.agents.get(n);if(!o)return this._handleError(new Error(`Agent not found: ${n}`),"AGENT_NOT_FOUND"),null;const a=o.config.provider||this.options.defaultProvider;this._emit("image-analysis-start",{agentId:n,provider:a,imageData:e,options:t});try{if("openai"===a){const s=(o.config.model||"gpt-4o").trim(),r={model:s,messages:[{role:"system",content:o.config.systemPrompt||"You are a helpful vision analysis assistant."},{role:"user",content:[{type:"text",text:t.prompt||"Please analyze this image."},{type:"image_url",image_url:{url:e,detail:t.detail||"high"}}]}],temperature:o.config.temperature||.7,max_tokens:o.config.maxTokens||500,top_p:o.config.topP||1,frequency_penalty:o.config.frequencyPenalty||0,presence_penalty:o.config.presencePenalty||0,stream:!1},i=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKeys.openai}`},body:JSON.stringify(r)}),l=await i.json();if(!i.ok)throw new Error(l.error?.message||"OpenAI image analysis error");return this._emit("image-analysis-complete",{agentId:n,provider:a,imageData:e,result:l}),l.choices[0].message.content}throw new Error(`Provider ${a} does not support image analysis`)}catch(e){return this._emit("image-processing-error",{agentId:n,error:e}),this._handleError(e,"IMAGE_PROCESSING_ERROR","Failed to analyze image"),null}}async analyzeImage(n,e,t={}){return this.processImage(n,e,t)}async generateImage(n,e,t={}){const o=this.agents.get(n);if(!o)return this._handleError(new Error(`Agent not found: ${n}`),"AGENT_NOT_FOUND"),null;const a=o.config.provider||this.options.defaultProvider;this._emit("image-generation-start",{agentId:n,provider:a,prompt:e,options:t});try{if("openai"===a){const s=(t.model||o.config.imageGenerationModel||"dall-e-3").trim(),r={prompt:e,n:t.n||1,size:t.size||"1024x1024",response_format:t.response_format||"url",user:n,model:s},i=await fetch("https://api.openai.com/v1/images/generations",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKeys.openai}`},body:JSON.stringify(r)}),l=await i.json();if(!i.ok)throw new Error(l.error?.message||"OpenAI image generation error");return this._emit("image-generation-complete",{agentId:n,provider:a,prompt:e,result:l}),l.data[0].url}throw new Error(`Provider ${a} does not support image generation`)}catch(e){return this._emit("image-generation-error",{agentId:n,error:e}),this._handleError(e,"IMAGE_GENERATION_ERROR","Failed to generate image"),null}}async editImage(n,e,t,o={}){const a=this.agents.get(n);if(!a)return this._handleError(new Error(`Agent not found: ${n}`),"AGENT_NOT_FOUND"),null;const s=a.config.provider||this.options.defaultProvider;this._emit("image-edit-start",{agentId:n,provider:s,prompt:t,options:o});try{if("openai"===s){const r=(o.model||a.config.model||"dalle-3").trim(),i={image:e,prompt:t,n:o.n||1,size:o.size||"1024x1024",response_format:o.response_format||"url",user:n,model:r},l=await fetch("https://api.openai.com/v1/images/edits",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKeys.openai}`},body:JSON.stringify(i)}),d=await l.json();if(!l.ok)throw new Error(d.error?.message||"OpenAI image edit error");return this._emit("image-edit-complete",{agentId:n,provider:s,prompt:t,result:d}),d.data[0].url}throw new Error(`Provider ${s} does not support image editing`)}catch(e){return this._emit("image-edit-error",{agentId:n,error:e}),this._handleError(e,"IMAGE_EDIT_ERROR","Failed to edit image"),null}}async variationImage(n,e,t={}){const o=this.agents.get(n);if(!o)return this._handleError(new Error(`Agent not found: ${n}`),"AGENT_NOT_FOUND"),null;const a=o.config.provider||this.options.defaultProvider;this._emit("image-variation-start",{agentId:n,provider:a,options:t});try{if("openai"===a){const s=(t.model||o.config.model||"dalle-3").trim(),r={image:e,n:t.n||1,size:t.size||"1024x1024",response_format:t.response_format||"url",user:n,model:s},i=await fetch("https://api.openai.com/v1/images/variations",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKeys.openai}`},body:JSON.stringify(r)}),l=await i.json();if(!i.ok)throw new Error(l.error?.message||"OpenAI image variation error");return this._emit("image-variation-complete",{agentId:n,provider:a,result:l}),l.data[0].url}throw new Error(`Provider ${a} does not support image variation`)}catch(e){return this._emit("image-variation-error",{agentId:n,error:e}),this._handleError(e,"IMAGE_VARIATION_ERROR","Failed to create image variation"),null}}}"undefined"!=typeof module&&module.exports?module.exports=e:n.Worksona=e}("undefined"!=typeof window?window:global);
|