@zinley/orion 1.2.1 → 1.2.2
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/dist/index.js +56 -56
- package/package.json +12 -14
package/dist/index.js
CHANGED
|
@@ -14,13 +14,13 @@ ${o} ${L.bold(e)}`)),t&&console.log(L.gray(` ${t}`)),s){let n=s.length>120?s.s
|
|
|
14
14
|
`);let n=s.slice(0,t).map(r=>L.gray(" ")+L.dim(r)).join(`
|
|
15
15
|
`);return n+=`
|
|
16
16
|
`+L.gray(` ... (${s.length-t} more lines)`),n}static error(e,t){c.customUIMode||(console.log(`
|
|
17
|
-
${L.red("✗")} ${L.red.bold(e)} ${L.red("ERROR")}`),console.log(L.gray(" ")+L.white(t)),console.log(""))}}});var Ge,Kt=F(()=>{"use strict";U();fe();Ge=class{toolNames=["read","Read"];async execute(e,t,s,o){let n=s.file_path||s.path,r=s.offset,a=s.limit;if(!n)throw new Error("Missing file_path or path argument");i.debug(`[ReadFileTool] Reading file: ${n}${r!==void 0?`, offset: ${r}`:""}${a!==void 0?`, limit: ${a}`:""}`);let l=Date.now();B.start("Read",s.description,n);try{let u=await import("fs/promises");try{await u.access(n)}catch{return[{type:"text",text:`Error: File does not exist at path: ${n}`}]}let g=await u.stat(n);if(g.isDirectory())return[{type:"text",text:`Error: Path is a directory, not a file: ${n}`}];let h=await u.readFile(n,"utf-8"),m=h.length,
|
|
18
|
-
`),S
|
|
17
|
+
${L.red("✗")} ${L.red.bold(e)} ${L.red("ERROR")}`),console.log(L.gray(" ")+L.white(t)),console.log(""))}}});var Ge,Kt=F(()=>{"use strict";U();fe();Ge=class{toolNames=["read","Read"];async execute(e,t,s,o){let n=s.file_path||s.path,r=s.offset,a=s.limit;if(!n)throw new Error("Missing file_path or path argument");i.debug(`[ReadFileTool] Reading file: ${n}${r!==void 0?`, offset: ${r}`:""}${a!==void 0?`, limit: ${a}`:""}`);let l=Date.now();B.start("Read",s.description,n);try{let u=await import("fs/promises");try{await u.access(n)}catch{return[{type:"text",text:`Error: File does not exist at path: ${n}`}]}let g=await u.stat(n);if(g.isDirectory())return[{type:"text",text:`Error: Path is a directory, not a file: ${n}`}];let h=await u.readFile(n,"utf-8"),m=h.length,S=h.split(`
|
|
18
|
+
`),w=S.length,p=Math.max(r??0,0),v=87500;if(m>v&&r===void 0&&a===void 0){let E=g.size/1024,_=E/1024,A=_>=1?`${_.toFixed(2)} MB`:`${E.toFixed(2)} KB`;return[{type:"text",text:`Error: File is too large to read completely.
|
|
19
19
|
|
|
20
20
|
File Information:
|
|
21
21
|
- Path: ${n}
|
|
22
|
-
- Size: ${
|
|
23
|
-
- Total Lines: ${
|
|
22
|
+
- Size: ${A} (${m} characters)
|
|
23
|
+
- Total Lines: ${w}
|
|
24
24
|
- Character Limit: ${v.toLocaleString()}
|
|
25
25
|
|
|
26
26
|
Suggested Solutions:
|
|
@@ -35,19 +35,19 @@ Suggested Solutions:
|
|
|
35
35
|
- Lines 2000-4000: Read(path: "${n}", offset: 2000, limit: 2000)
|
|
36
36
|
- And so on...
|
|
37
37
|
|
|
38
|
-
The file has ${
|
|
38
|
+
The file has ${w.toLocaleString()} total lines. You can read approximately 2000 lines at a time safely.`}]}if(w===0||h.length===0)return[{type:"text",text:"File is empty (0 lines)"}];if(p>=w)return[{type:"text",text:`Error: Offset ${p} is beyond file length. File has ${w} total lines. Try a smaller offset (0 to ${w-1}).`}];let f=a!==void 0?Math.min(p+a,w):w,I=S.slice(p,f),P=I.map((E,_)=>`${(p+_+1).toString().padStart(6," ")} ${E}`).join(`
|
|
39
39
|
`),D=P;if(r!==void 0||a!==void 0){let E=`
|
|
40
40
|
|
|
41
|
-
[Read ${I.length} lines (${p+1}-${f}) of ${
|
|
41
|
+
[Read ${I.length} lines (${p+1}-${f}) of ${w} total lines]`;D=P+E}let C=Date.now()-l;return B.result({toolName:"Read",filePath:n,output:D,success:!0,executionTime:C}),[{type:"text",text:D}]}catch(u){i.debug(`[ReadFileTool] Failed to read file: ${u.message}`);let g;u.code==="ENOENT"?g=`Error: File does not exist at path: ${n}`:u.code==="EACCES"?g=`Error: Permission denied. Cannot read file: ${n}`:u.code==="EISDIR"?g=`Error: Path is a directory, not a file: ${n}`:g=`Error reading file: ${u.message}`;let h=Date.now()-l;return B.result({toolName:"Read",filePath:n,output:g,success:!1,executionTime:h}),[{type:"text",text:g}]}}}});import vt from"fs/promises";import Zs from"form-data";import bt from"axios";import St from"path";var qe,Jt=F(()=>{"use strict";U();fe();qe=class{toolNames=["read_special_file","ReadSpecialFile"];baseEndpoint="https://snowx.ai/md";maxPollAttempts=60;pollInterval=2e3;supportedExtensions=["pdf","docx","doc","xlsx","xls","pptx","ppt","mp3","mp4","wav","html","htm"];async execute(e,t,s,o){let n=s.path;if(!n)throw new Error("Missing path argument");i.debug(`[ReadSpecialFileTool] Converting file: ${n}`);let r=Date.now();B.start("ReadSpecialFile",s.description,n);try{try{await vt.access(n)}catch{return[{type:"text",text:`Error: File does not exist at path: ${n}`}]}let a=St.extname(n).substring(1).toLowerCase();if(!this.supportedExtensions.includes(a)){let P=this.supportedExtensions.join(", ");return[{type:"text",text:`Error: Unsupported file type '${a}'. The read_special_file tool only supports Microsoft Office documents (docx, doc, xlsx, xls, pptx, ppt), PDF files (pdf), audio/video files (mp3, mp4, wav), and web files (html, htm). For plain text files, use the run_command tool with 'cat' instead.
|
|
42
42
|
|
|
43
|
-
Supported file types: ${P}`}]}let l=await vt.stat(n),u=St.basename(n);i.debug(`[ReadSpecialFileTool] Converting ${a.toUpperCase()} file: ${u} (${l.size} bytes)`);let g=await this.uploadToBatchAPI(n,u);i.debug(`[ReadSpecialFileTool] Uploaded successfully, request_id: ${g}`);let h=await this.pollBatchStatus(g);i.debug("[ReadSpecialFileTool] Conversion completed");let m=h.files[0];if(!m||m.status==="failed"){let P=m?.error||"Unknown conversion error";return[{type:"text",text:`Error converting ${a.toUpperCase()} file: ${P}`}]}let
|
|
43
|
+
Supported file types: ${P}`}]}let l=await vt.stat(n),u=St.basename(n);i.debug(`[ReadSpecialFileTool] Converting ${a.toUpperCase()} file: ${u} (${l.size} bytes)`);let g=await this.uploadToBatchAPI(n,u);i.debug(`[ReadSpecialFileTool] Uploaded successfully, request_id: ${g}`);let h=await this.pollBatchStatus(g);i.debug("[ReadSpecialFileTool] Conversion completed");let m=h.files[0];if(!m||m.status==="failed"){let P=m?.error||"Unknown conversion error";return[{type:"text",text:`Error converting ${a.toUpperCase()} file: ${P}`}]}let S=await this.fetchFileContent(m.file_id);if(!S.markdown_content)return[{type:"text",text:"Error: No markdown content returned from conversion service"}];let w=l.size/1024,p=w/1024,v=p>=1?`${p.toFixed(2)} MB`:`${w.toFixed(2)} KB`,f=`# File: ${u}
|
|
44
44
|
**Type:** ${a.toUpperCase()}
|
|
45
45
|
**Size:** ${v}
|
|
46
46
|
**Conversion:** ✅ Successful
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
-
${
|
|
50
|
+
${S.markdown_content}`,I=Date.now()-r;return B.result({toolName:"ReadSpecialFile",filePath:n,output:`Successfully converted ${u} (${v})`,success:!0,executionTime:I}),[{type:"text",text:f}]}catch(a){i.debug(`[ReadSpecialFileTool] Failed to convert file: ${a.message}`);let l=`Error converting file: ${a.message}
|
|
51
51
|
|
|
52
52
|
This could be due to:
|
|
53
53
|
• File corruption or invalid format
|
|
@@ -59,26 +59,26 @@ For plain text files (.txt, .json, .py, etc.), use the run_command tool with 'ca
|
|
|
59
59
|
`),l="";for(let h=0;h<Math.min(a.length,8);h++)l+=`+ ${a[h]}
|
|
60
60
|
`;a.length>8&&(l+=`+ ...
|
|
61
61
|
|
|
62
|
-
(${a.length-8} more lines)`);let u=l.trim();i.debug(`[WriteFileTool] Successfully wrote ${t.length} characters`);let g=Date.now()-s;return B.result({toolName:"Write",filePath:e,output:u,success:!0,executionTime:g}),[{type:"text",text:u}]}catch(o){i.debug(`[WriteFileTool] Failed to write file: ${o.message}`);let n=`Error writing file: ${o.message}`,r=Date.now()-s;return B.result({toolName:"Write",filePath:e,output:n,success:!1,executionTime:r}),[{type:"text",text:n}]}}async executeEditsMode(e,t,s){if(!t||!Array.isArray(t)||t.length===0)throw new Error("Missing content or edits array");if(t.length>50)throw new Error("Too many edit operations. Maximum 50 edits allowed per operation.");i.debug(`[WriteFileTool] Writing file: ${e} with ${t.length} edits`);try{let o=await import("fs/promises"),n=await import("path");if(!e||typeof e!="string")throw new Error("Invalid file_path parameter");if(e.startsWith("~/"))throw new Error(`Home directory shortcut not allowed ('${e}'). Use full absolute path instead.`);if(!e.startsWith("/")&&!e.includes(":\\"))throw new Error(`File path appears to be relative ('${e}'). Use full absolute path starting from root.`);for(let
|
|
63
|
-
`),p="";for(let v=0;v<Math.min(
|
|
64
|
-
`;return
|
|
62
|
+
(${a.length-8} more lines)`);let u=l.trim();i.debug(`[WriteFileTool] Successfully wrote ${t.length} characters`);let g=Date.now()-s;return B.result({toolName:"Write",filePath:e,output:u,success:!0,executionTime:g}),[{type:"text",text:u}]}catch(o){i.debug(`[WriteFileTool] Failed to write file: ${o.message}`);let n=`Error writing file: ${o.message}`,r=Date.now()-s;return B.result({toolName:"Write",filePath:e,output:n,success:!1,executionTime:r}),[{type:"text",text:n}]}}async executeEditsMode(e,t,s){if(!t||!Array.isArray(t)||t.length===0)throw new Error("Missing content or edits array");if(t.length>50)throw new Error("Too many edit operations. Maximum 50 edits allowed per operation.");i.debug(`[WriteFileTool] Writing file: ${e} with ${t.length} edits`);try{let o=await import("fs/promises"),n=await import("path");if(!e||typeof e!="string")throw new Error("Invalid file_path parameter");if(e.startsWith("~/"))throw new Error(`Home directory shortcut not allowed ('${e}'). Use full absolute path instead.`);if(!e.startsWith("/")&&!e.includes(":\\"))throw new Error(`File path appears to be relative ('${e}'). Use full absolute path starting from root.`);for(let S=0;S<t.length;S++){let w=t[S];if(!w||typeof w!="object")throw new Error(`Edit operation ${S+1} must be an object with 'search' and 'replace' fields`);if(!w.hasOwnProperty("search")||typeof w.search!="string")throw new Error(`Edit operation ${S+1} missing required 'search' field (must be string)`);if(!w.hasOwnProperty("replace")||typeof w.replace!="string")throw new Error(`Edit operation ${S+1} missing required 'replace' field (must be string)`)}let r=t[0].search==="",a;if(r)if(i.debug("[WriteFileTool] Creating new file"),a="",t.length===1&&t[0].search===""){a=t[0].replace;let S=n.dirname(e);await o.mkdir(S,{recursive:!0}),await o.writeFile(e,a,"utf-8");let w=a.split(`
|
|
63
|
+
`),p="";for(let v=0;v<Math.min(w.length,8);v++)p+=`+ ${w[v]}
|
|
64
|
+
`;return w.length>8&&(p+=`+ ...
|
|
65
65
|
|
|
66
|
-
(${
|
|
67
|
-
`),m="";for(let
|
|
66
|
+
(${w.length-8} more lines)`),i.debug(`[WriteFileTool] Created new file with ${a.length} characters`),[{type:"text",text:p.trim()}]}else throw new Error("For new files, only one edit with empty search string is allowed");else{i.debug("[WriteFileTool] Reading existing file");try{a=await o.readFile(e,"utf-8"),i.debug(`[WriteFileTool] Read ${a.length} characters from existing file`)}catch(S){throw S.code==="ENOENT"?new Error(`File does not exist at path: ${e}. Use empty search string to create new file.`):new Error(`Failed to read existing file: ${S.message}`)}}let l=0,u=a,g=[];for(let S=0;S<t.length;S++){let w=t[S];if(i.debug(`[WriteFileTool] Applying edit ${S+1}/${t.length}`),w.search==="")if(r){g.push({index:S+1,success:!0,message:"Skipped (empty search string for new file)",replacementCount:0});continue}else{i.debug("[WriteFileTool] Rewriting entire existing file"),u=w.replace,g.push({index:S+1,success:!0,message:"Successfully rewrote entire file",replacementCount:1}),l++;continue}let p=u.indexOf(w.search);if(p!==-1)u=u.substring(0,p)+w.replace+u.substring(p+w.search.length),i.debug("[WriteFileTool] Replaced first occurrence"),g.push({index:S+1,success:!0,message:"Successfully replaced first occurrence",replacementCount:1}),l++;else{let v=`Search string not found: '${w.search}'`;return g.push({index:S+1,success:!1,message:v,replacementCount:0}),[{type:"text",text:`Error: Search string not found in edit ${S+1}: '${w.search}'\\n\\nEdit Summary:\\n- Total edits: ${g.length}\\n- Successful: ${g.filter(I=>I.success).length}\\n- Failed: ${g.filter(I=>!I.success).length}\\n\\nIndividual Edit Results:\\n`+g.map(I=>`${I.success?"✅":"❌"} Edit ${I.index}: ${I.message}`).join("\\n")}]}}await o.writeFile(e,u,"utf-8"),i.debug(`[WriteFileTool] Successfully wrote ${u.length} characters to file`);let h=u.split(`
|
|
67
|
+
`),m="";for(let S=0;S<Math.min(h.length,8);S++)m+=`+ ${h[S]}
|
|
68
68
|
`;return h.length>8&&(m+=`+ ...
|
|
69
69
|
|
|
70
|
-
(${h.length-8} more lines)`),[{type:"text",text:m.trim()}]}catch(o){return i.debug(`[WriteFileTool] Failed to write file: ${o.message}`),[{type:"text",text:`Error writing file: ${o.message}`}]}}}});var He,Zt=F(()=>{"use strict";U();fe();He=class{toolNames=["edit","Edit"];async execute(e,t,s,o){let n=s.file_path,r=s.old_string,a=s.new_string,l=s.replace_all===!0;if(!n)throw new Error("Missing file_path argument");if(r==null)throw new Error("Missing old_string argument");if(a==null)throw new Error("Missing new_string argument");i.debug(`[EditFileTool] Editing file: ${n}`);let u=Date.now();B.start("Edit",s.description,n);try{let g=await import("fs/promises"),h=await g.readFile(n,"utf-8"),m,
|
|
70
|
+
(${h.length-8} more lines)`),[{type:"text",text:m.trim()}]}catch(o){return i.debug(`[WriteFileTool] Failed to write file: ${o.message}`),[{type:"text",text:`Error writing file: ${o.message}`}]}}}});var He,Zt=F(()=>{"use strict";U();fe();He=class{toolNames=["edit","Edit"];async execute(e,t,s,o){let n=s.file_path,r=s.old_string,a=s.new_string,l=s.replace_all===!0;if(!n)throw new Error("Missing file_path argument");if(r==null)throw new Error("Missing old_string argument");if(a==null)throw new Error("Missing new_string argument");i.debug(`[EditFileTool] Editing file: ${n}`);let u=Date.now();B.start("Edit",s.description,n);try{let g=await import("fs/promises"),h=await g.readFile(n,"utf-8"),m,S=0;if(l)for(m=h;m.includes(r);)m=m.replace(r,a),S++;else h.includes(r)?(m=h.replace(r,a),S=1):m=h;if(S===0){let I=`No matches found for the specified old_string in file: ${n}`,P=Date.now()-u;return B.result({toolName:"Edit",filePath:n,output:I,success:!1,executionTime:P}),[{type:"text",text:I}]}await g.writeFile(n,m,"utf-8");let w=`Successfully edited file: Replaced ${S} occurrence(s)`;i.debug(`[EditFileTool] ${w}`);let p=Date.now()-u,v=(await import("chalk")).default,f=`${v.red("- "+r.split(`
|
|
71
71
|
`).slice(0,5).join(`
|
|
72
72
|
- `))}
|
|
73
73
|
${v.green("+ "+a.split(`
|
|
74
74
|
`).slice(0,5).join(`
|
|
75
75
|
+ `))}
|
|
76
76
|
|
|
77
|
-
Replaced ${
|
|
77
|
+
Replaced ${S} occurrence(s)`;return B.result({toolName:"Edit",filePath:n,output:f,success:!0,executionTime:p}),[{type:"text",text:w}]}catch(g){i.debug(`[EditFileTool] Failed to edit file: ${g.message}`);let h=`Error editing file: ${g.message}`,m=Date.now()-u;return B.result({toolName:"Edit",filePath:n,output:h,success:!1,executionTime:m}),[{type:"text",text:h}]}}}});var Ve,es=F(()=>{"use strict";U();Ve=class{toolNames=["upload_file"];async execute(e,t,s,o){let n=s.file_path;if(!n)throw new Error("Missing file_path argument");return i.debug(`[UploadFileTool] Upload file not implemented for CLI: ${n}`),[{type:"text",text:`Upload file functionality not available in CLI version: ${n}`}]}}});var ts=F(()=>{"use strict"});function Re(c){let t=c.trim().toLowerCase().split(/\s+/)[0]||"",s=new Set(["echo","pwd","date","whoami","id","hostname","uname","which","type","true","false","yes","printf"]),o=new Set(["ls","cat","head","tail","wc","grep","awk","sed","sort","uniq","cut","tr","basename","dirname","stat","file","du","df","free","uptime","ps"]),n=new Set(["make","cmake","npm","yarn","pip","cargo","mvn","gradle","docker","git","rsync","scp","ssh","curl","wget","find","locate","tar","zip","unzip","brew","apt","yum"]);return s.has(t)||o.has(t)&&c.length<100?Te.fast:n.has(t)?Te.extended:c.length<20?Te.fast:c.includes("|")||c.includes(">")||c.includes("<")?c.length<200?Te.default:Te.extended:Te.default}var Te,wt=F(()=>{"use strict";ts();Te={fast:{activityTimeout:2e3,maxTimeout:5e3,initialTimeout:1e3},default:{activityTimeout:1e4,maxTimeout:6e4,initialTimeout:5e3},extended:{activityTimeout:3e4,maxTimeout:3e5,initialTimeout:1e4}}});import{spawn as en}from"child_process";var Pe,ss=F(()=>{"use strict";wt();Pe=class c{static instance;constructor(){}static getInstance(){return c.instance||(c.instance=new c),c.instance}async executeCommand(e,t,s,o,n="new",r){let a=r||Re(e);return this.executeInNewProcess(e,a)}async executeInNewProcess(e,t){return new Promise(s=>{let o=en("/bin/bash",["-c",e],{env:process.env,stdio:["ignore","pipe","pipe"]}),n="",r="",a=!1,l=setTimeout(()=>{o.killed||(a=!0,console.log("⏰ Timeout reached, sending SIGTERM..."),o.kill("SIGTERM"),setTimeout(()=>{o.killed||(console.log("❌ Process didn't respond to SIGTERM, sending SIGKILL..."),o.kill("SIGKILL"))},5e3))},t.maxTimeout);o.stdout.on("data",u=>{n+=u.toString()}),o.stderr.on("data",u=>{r+=u.toString()}),o.on("close",u=>{clearTimeout(l);let g=(n+r).trim(),h=3e4;if(g.length>h){let m=g.substring(0,h),w=m.split(`
|
|
78
78
|
`).length,p=g.length;g=m+`
|
|
79
79
|
|
|
80
80
|
[Output truncated at `+h+` characters]
|
|
81
|
-
[Showing first `+
|
|
81
|
+
[Showing first `+w+` lines of output]
|
|
82
82
|
[Total output was `+p+" characters]",console.log("⚠️ Output truncated: "+p+" chars -> "+h+" chars")}a?(console.log("⏰ Command timed out"),s({output:g+`
|
|
83
83
|
|
|
84
84
|
❌ Command timed out after `+t.maxTimeout+" milliseconds",exitCode:-15,isSuccess:!1})):s({output:g,exitCode:u||0,isSuccess:(u||0)===0})}),o.on("error",u=>{clearTimeout(l),s({output:"Process execution failed: "+u.message+`
|
|
@@ -122,7 +122,7 @@ Command: ${e}
|
|
|
122
122
|
|
|
123
123
|
Note: The process will continue running in the background.
|
|
124
124
|
Output will be collected automatically.`;return console.log(`✅ Started background process ${r} (PID: ${a.pid})`),{success:!0,result:{process_id:r,pid:a.pid,message:u}}}let o=t?{activityTimeout:t,maxTimeout:t,initialTimeout:t}:Re(e),n=await this.shellSessionManager.executeCommand(e,`tool-${Date.now()}`,this.currentUserId,"new","new",o);return{success:n.isSuccess,result:{command:e,stdout:n.output,stderr:"",exit_code:n.exitCode}}}catch(e){return{success:!1,error:`Bash command failed: ${e.message}`}}}async editFile(c){try{let{file_path:e,old_string:t,new_string:s,replace_all:o=!1}=c;if(t===s)throw new Error("No changes to make: old_string and new_string are identical");if(e.endsWith(".ipynb")&&re.existsSync(e)){let a=await z.readFile(e,"utf-8"),l=JSON.parse(a);for(let u=0;u<l.cells.length;u++){let g=l.cells[u],h=Array.isArray(g.source)?g.source.join(""):g.source;if(h.includes(t)){let m=o?h.replaceAll(t,s):h.replace(t,s);return l.cells[u].source=m,await z.writeFile(e,JSON.stringify(l,null,2),"utf-8"),{success:!0,result:{file_path:e,replacements:o?h.split(t).length-1:1,message:"Notebook cell edited successfully"}}}}throw new Error("String not found in notebook. The old_string does not exist in any cell.")}await this.validateFileNotModified(e);let n=await z.readFile(e,"utf-8");if(!n.includes(t))throw new Error("String not found in file. Check for whitespace/indentation differences.");let r=o?n.replaceAll(t,s):n.replace(t,s);if(r===n)throw new Error("Edit failed: File content unchanged after replacement");return await z.writeFile(e,r,"utf-8"),this.cacheFileState(e,r),{success:!0,result:{file_path:e,replacements:o?n.split(t).length-1:1,message:"File edited successfully"}}}catch(e){return{success:!1,error:`Edit failed: ${e.message}`}}}async grepFiles(c){try{let{pattern:e,path:t=process.cwd(),glob:s,output_mode:o="files_with_matches",case_insensitive:n=!1}=c,r=[];return n&&r.push("-i"),o==="files_with_matches"?r.push("-l"):o==="count"&&r.push("-c"),s&&r.push("--glob",s),r.push(e,t),new Promise(a=>{let l=os("rg",r,{stdio:["ignore","pipe","pipe"]}),u="",g="";l.stdout.on("data",h=>{u+=h.toString()}),l.stderr.on("data",h=>{g+=h.toString()}),l.on("close",h=>{if(h!==0&&h!==1){a({success:!1,error:`ripgrep failed: ${g||"Unknown error"}`});return}let m=u.trim().split(`
|
|
125
|
-
`).filter(
|
|
125
|
+
`).filter(w=>w),S=m.length;a({success:!0,result:{pattern:e,num_files:S,files:m,output:u.trim()}})}),l.on("error",h=>{a({success:!1,error:`Failed to execute ripgrep: ${h.message}. Make sure ripgrep is installed.`})})})}catch(e){return{success:!1,error:`Grep failed: ${e.message}`}}}async globFiles(c){try{let{pattern:e,path:t=process.cwd()}=c,o=(a=>{let l=a;return l=l.replace(/[.+^${}()|[\]\\]/g,"\\$&"),l=l.replace(/\*\*/g,"<DOUBLESTAR>"),l=l.replace(/\*/g,"[^/]*"),l=l.replace(/<DOUBLESTAR>/g,".*"),l=l.replace(/\?/g,"."),new RegExp(`^${l}$`)})(e),n=[],r=async a=>{try{let l=await z.readdir(a,{withFileTypes:!0});for(let u of l){if(u.name.startsWith("."))continue;let g=Ce.join(a,u.name),h=Ce.relative(t,g);u.isDirectory()?await r(g):(o.test(h)||o.test(u.name))&&n.push(g)}}catch{}};return await r(t),{success:!0,result:{pattern:e,num_files:n.length,files:n}}}catch(e){return{success:!1,error:`Glob failed: ${e.message}`}}}async editNotebook(c){try{let{notebook_path:e,cell_id:t,new_source:s,cell_type:o="code",edit_mode:n="replace"}=c;if(!re.existsSync(e))throw new Error(`Notebook file does not exist: ${e}`);if(!e.endsWith(".ipynb"))throw new Error("File must be a Jupyter notebook (.ipynb file)");let r=await z.readFile(e,"utf-8"),a=JSON.parse(r);switch(n){case"replace":{if(!t)throw new Error("cell_id is required for replace mode");let l=a.cells.findIndex(u=>u.id===t);if(l===-1)throw new Error(`Cell with id ${t} not found`);a.cells[l].source=s;break}case"insert":{if(!o)throw new Error("cell_type is required for insert mode");let l={id:Math.random().toString(36).substring(2,15),cell_type:o,source:s,metadata:{},execution_count:o==="code"?null:void 0,outputs:o==="code"?[]:void 0};if(t){let u=a.cells.findIndex(g=>g.id===t);a.cells.splice(u+1,0,l)}else a.cells.unshift(l);break}case"delete":{if(!t)throw new Error("cell_id is required for delete mode");let l=a.cells.findIndex(u=>u.id===t);if(l===-1)throw new Error(`Cell with id ${t} not found`);a.cells.splice(l,1);break}default:throw new Error(`Invalid edit_mode: ${n}`)}return await z.writeFile(e,JSON.stringify(a,null,2),"utf-8"),{success:!0,result:{notebook_path:e,edit_mode:n,cell_id:t,message:"Notebook edited successfully"}}}catch(e){return{success:!1,error:`NotebookEdit failed: ${e.message}`}}}cacheFileState(c,e){try{let t=re.statSync(c);this.fileStateCache.set(c,{content:e,modificationDate:t.mtime,filePath:c})}catch{}}async validateFileNotModified(c){let e=this.fileStateCache.get(c);if(!e){if(re.existsSync(c)){let s=await z.readFile(c,"utf-8");this.cacheFileState(c,s)}return}if(re.statSync(c).mtime.getTime()!==e.modificationDate.getTime())throw new Error("File has been modified since last read. Read it again before editing.")}getAvailableTools(){let c=[];for(let[e,t]of this.tools.entries())t.enabled&&c.push({type:"function",function:{name:e,description:t.description,parameters:t.parameters}});return c}getToolsByCategory(c){return this.getAvailableTools().filter(e=>this.tools.get(e.function.name)?.category===c)}enableTool(c){let e=this.tools.get(c);return e?(e.enabled=!0,!0):!1}disableTool(c){let e=this.tools.get(c);return e?(e.enabled=!1,!0):!1}getExecutionHistory(c=10){return this.executionHistory.slice(-c)}getExecutionStats(){let c=this.executionHistory.length,e=this.executionHistory.filter(r=>r.result.success).length,t=c-e,s=c>0?this.executionHistory.reduce((r,a)=>r+a.executionTime,0)/c:0,o=new Map;this.executionHistory.forEach(r=>{o.set(r.toolName,(o.get(r.toolName)||0)+1)});let n=o.size>0?Array.from(o.entries()).reduce((r,a)=>a[1]>r[1]?a:r)[0]:null;return{total:c,successful:e,failed:t,averageTime:Math.round(s),mostUsed:n}}clearHistory(){this.executionHistory=[]}setUserId(c){this.currentUserId=c}getCurrentUserId(){return this.currentUserId}cleanupUserSession(c){console.log(`[ToolCalling] Session cleanup not needed for 'new' mode (session: ${c||"none"})`)}handleLargeResponse(c,e){if(!c.success||!c.result)return c;let t=typeof c.result=="string"?c.result:JSON.stringify(c.result);if(t.length>this.maxResponseCharacters){let s=this.createTempFile(t,e);return s?{success:!0,result:this.generatePreview(t,s)}:{success:!0,result:this.truncateOutput(t)}}return c}createTempFile(c,e){try{let t=on.tmpdir(),s=Ce.join(t,"orion_tool_responses");re.existsSync(s)||re.mkdirSync(s,{recursive:!0});let o=Math.floor(Date.now()/1e3),n=Math.random().toString(36).substring(2,10),r=`${e}_${o}_${n}.txt`,a=Ce.join(s,r);return re.writeFileSync(a,c,"utf8"),a}catch{return null}}generatePreview(c,e){let t=c.substring(0,1e4),s=`📄 Response too large (${c.length} characters > 87,500 limit), saved to temporary file.
|
|
126
126
|
|
|
127
127
|
`;return s+=`📁 TEMP FILE PATH: ${e}
|
|
128
128
|
`,s+=`🔍 Use read_file, grep, cat, or other tools to access the full content.
|
|
@@ -135,18 +135,18 @@ ${"─".repeat(50)}`,s+=`
|
|
|
135
135
|
|
|
136
136
|
💡 To read full content: use tools like 'read_file' with path above`,s}truncateOutput(c){return c.length<=this.maxResponseCharacters?c:c.substring(0,this.maxResponseCharacters)+`
|
|
137
137
|
|
|
138
|
-
... (truncated due to size limit)`}stopAllRunningTools(){}}});var je,is=F(()=>{"use strict";U();je=class{toolNames=["bash","Bash","run_command"];async execute(e,t,s,o){let n=s.command,r=s.session||"new",a=s.description,l=s.timeout,u=s.run_in_background;if(!n)throw new Error("Missing command argument");if(n.trim().length===0)throw new Error("Command cannot be empty");if(r!=="new"&&r!=="existing")throw new Error(`Invalid session mode '${r}' - must be 'new' or 'existing'`);if(l!==void 0){if(l<=0)throw new Error(`Timeout must be positive. Received: ${l}ms`);if(l>6e5)throw new Error(`Timeout cannot exceed 600000ms (10 minutes). Received: ${l}ms`)}let g=l||12e4;i.debug(`[RunCommandTool] Executing bash command: ${n.substring(0,50)}${n.length>50?"...":""}`),a&&i.debug(`[RunCommandTool] Description: ${a}`),i.debug(`[RunCommandTool] Session: ${r}, Timeout: ${g}ms, Background: ${u||!1}`);try{let h=(await Promise.resolve().then(()=>(ze(),yt))).ToolCallingService.getInstance(),m={id:e,type:"function",function:{name:"execute_command",arguments:JSON.stringify({command:n,session:r,timeout:g})}},
|
|
139
|
-
`,
|
|
138
|
+
... (truncated due to size limit)`}stopAllRunningTools(){}}});var je,is=F(()=>{"use strict";U();je=class{toolNames=["bash","Bash","run_command"];async execute(e,t,s,o){let n=s.command,r=s.session||"new",a=s.description,l=s.timeout,u=s.run_in_background;if(!n)throw new Error("Missing command argument");if(n.trim().length===0)throw new Error("Command cannot be empty");if(r!=="new"&&r!=="existing")throw new Error(`Invalid session mode '${r}' - must be 'new' or 'existing'`);if(l!==void 0){if(l<=0)throw new Error(`Timeout must be positive. Received: ${l}ms`);if(l>6e5)throw new Error(`Timeout cannot exceed 600000ms (10 minutes). Received: ${l}ms`)}let g=l||12e4;i.debug(`[RunCommandTool] Executing bash command: ${n.substring(0,50)}${n.length>50?"...":""}`),a&&i.debug(`[RunCommandTool] Description: ${a}`),i.debug(`[RunCommandTool] Session: ${r}, Timeout: ${g}ms, Background: ${u||!1}`);try{let h=(await Promise.resolve().then(()=>(ze(),yt))).ToolCallingService.getInstance(),m={id:e,type:"function",function:{name:"execute_command",arguments:JSON.stringify({command:n,session:r,timeout:g})}},S=await h.executeTool(m),w="";if(S.success){let p=(S.result?.stdout||"").trim(),v=S.result?.exitCode??0;if(w=`Command: ${n}
|
|
139
|
+
`,w+=`Exit Code: ${v}
|
|
140
140
|
|
|
141
141
|
`,p.length>0){let f=p.split(`
|
|
142
|
-
`),I=f.slice(0,15);
|
|
143
|
-
`),f.length>15&&(
|
|
142
|
+
`),I=f.slice(0,15);w+=I.join(`
|
|
143
|
+
`),f.length>15&&(w+=`
|
|
144
144
|
|
|
145
|
-
... (showing first 15 of ${f.length} lines)`)}else
|
|
146
|
-
`,
|
|
145
|
+
... (showing first 15 of ${f.length} lines)`)}else w+="(no output)";return[{type:"text",text:w}]}else{let p=S.error||"Unknown error",v=S.result?.exitCode??1;return w=`Command: ${n}
|
|
146
|
+
`,w+=`Exit Code: ${v}
|
|
147
147
|
|
|
148
|
-
`,
|
|
149
|
-
${p}`,[{type:"text",text:
|
|
148
|
+
`,w+=`Error:
|
|
149
|
+
${p}`,[{type:"text",text:w}]}}catch(h){return i.debug(`[RunCommandTool] Failed to execute bash command: ${h.message}`),[{type:"text",text:`Command: ${n}
|
|
150
150
|
Error: ${h.message}`}]}}ensureMeaningfulOutput(e,t,s){let o=(e||"").trim();return o.length===0?s?`✅ Command '${t}' executed successfully.
|
|
151
151
|
|
|
152
152
|
ℹ️ No output was produced, which may be expected for this operation. This typically means:
|
|
@@ -164,21 +164,21 @@ If you expected output, the command may need different parameters or the operati
|
|
|
164
164
|
Consider:
|
|
165
165
|
• Checking the command syntax and parameters
|
|
166
166
|
• Verifying file permissions and paths
|
|
167
|
-
• Running the command with verbose flags for more details`:o}}});var Qe,rs=F(()=>{"use strict";U();Qe=class{toolNames=["grep","Grep"];async execute(e,t,s,o){let n=s.pattern,r=s.output_mode||"files_with_matches",a=s.path||process.cwd(),l=s.glob,u=s.type,g=s["-i"]===!0,h=s["-n"]===!0,m=s["-A"],
|
|
168
|
-
|
|
169
|
-
[Found ${
|
|
170
|
-
`).length} matching line(s)]`;return[{type:"text",text:
|
|
171
|
-
`);return[{type:"text",text:`Found ${
|
|
172
|
-
${
|
|
173
|
-
`)}`}]}catch(a){return i.debug(`[GlobTool] Glob failed: ${a.message}`),[{type:"text",text:"No files found matching pattern"}]}}}});var Je,cs=F(()=>{"use strict";U();Je=class{toolNames=["open_url"];async execute(e,t,s,o){let n=s.url;if(!n)throw new Error("Missing url argument");i.debug(`[OpenUrlTool] Opening URL: ${n}`),o.activeWebViewURLs.includes(n)||(o.activeWebViewURLs.push(n),i.debug(`[OpenUrlTool] Added to active URLs: ${n}`));try{let{exec:r}=await import("child_process"),a=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";return r(`${a} "${n}"`,l=>{l?i.debug(`[OpenUrlTool] Failed to open URL in browser: ${l.message}`):i.debug(`[OpenUrlTool] URL opened in default browser: ${n}`)}),[{type:"text",text:`✅ URL opened in default browser: ${n}`}]}catch(r){return i.debug(`[OpenUrlTool] Failed to open URL: ${r.message}`),[{type:"text",text:`❌ Failed to open URL: ${r.message}`}]}}}});var Ye,ls=F(()=>{"use strict";U();Ye=class{toolNames=["manage_device_knowledge"];async execute(e,t,s,o){let n=s.action;return i.debug(`[ManageDeviceKnowledgeTool] Device knowledge management not implemented: ${n}`),[{type:"text",text:`Device knowledge management not available in CLI version: ${n}`}]}}});var Ze,us=F(()=>{"use strict";U();Ze=class{toolNames=["operator_status"];async execute(e,t,s,o){let n=s.taskId,r=s.status,a=s.message;return i.debug(`[OperatorStatusTool] Operator status - Task ${n}: ${r} - ${a}`),[{type:"text",text:"Operator status updated successfully"}]}}});var et,ds=F(()=>{"use strict";U();et=class{toolNames=["provide_input"];async execute(e,t,s,o){let n=s.input;if(!n)throw new Error("Missing input argument");i.debug(`[ProvideInputTool] Delegating provide_input to backend: ${n.substring(0,20)}...`);try{let r=(await Promise.resolve().then(()=>(ze(),yt))).ToolCallingService.getInstance(),a={id:`provide_input_${Date.now()}`,type:"function",function:{name:"provide_input",arguments:JSON.stringify({input:n})}},l=await r.executeTool(a);return l.success?[{type:"text",text:l.result?.message||"Input provided successfully"}]:[{type:"text",text:`Error: ${l.error||"Failed to provide input"}`}]}catch(r){return i.debug(`[ProvideInputTool] Failed to delegate provide_input: ${r.message}`),[{type:"text",text:`Error: ${r.message}`}]}}}});function ps(c){c.register(new Ge),c.register(new qe),c.register(new Xe),c.register(new He),c.register(new Ve),c.register(new je),c.register(new Qe),c.register(new Ke),c.register(new Je),c.register(new Ye),c.register(new Ze),c.register(new et)}var gs=F(()=>{"use strict";Kt();Jt();Yt();Zt();es();is();rs();as();cs();ls();us();ds()});var tt,ms=F(()=>{"use strict";tt=class{constructor(e,t,s,o,n){this.userId=e;this.sessionId=t;this.toolCallId=s;this.runningProcesses=o;this.activeWebViewURLs=n}}});var hs={};te(hs,{FrontendWebSocketService:()=>V});import{EventEmitter as rn}from"events";import an from"ws";var V,Fe=F(()=>{"use strict";U();de();se();Le();jt();gs();ms();V=class c extends rn{static instance;webSocket=null;serverHost;deviceId=null;userId=null;sessionId=null;deviceRegistrationService;authService;toolRegistry;isConnected=!1;connectionError=null;isConnecting=!1;runningProcesses=new Map;activeWebViewURLs=[];isConversationActive=!1;heartbeatTimer=null;constructor(e="ws.snowx.ai",t,s="node"){super(),this.serverHost=e,this.userId=t||null,this.deviceRegistrationService=ne.getInstance(),this.authService=q.getInstance(),this.deviceId=this.generateUniqueDeviceId(t,s),this.toolRegistry=new Be,ps(this.toolRegistry),i.debug("[FRONTEND WS] Tool registry initialized with 11 frontend tools"),this.deviceId?i.debug(`[FRONTEND WS] Client initialized - Using consistent Device ID: ${this.deviceId}`):i.warn("[FRONTEND WS] Client initialized without device ID - will be set on authentication")}static getInstance(){return c.instance||(c.instance=new c),c.instance}generateUniqueDeviceId(e,t="node"){if(e){let s=this.deviceRegistrationService.getCurrentDeviceId();if(s)return s}return i.warn("[FRONTEND WS] No device ID available from DeviceRegistrationService"),null}async connectForConversation(e,t){if(e&&e!==this.userId&&(this.userId=e),this.userId){let o=this.generateUniqueDeviceId(this.userId,"node");if(o&&this.deviceId!==o)i.debug(`[FRONTEND WS] Device ID changed from ${this.deviceId} to ${o} (using consistent ID from DeviceRegistrationService)`),this.deviceId=o;else if(o)i.debug(`[FRONTEND WS] Using existing consistent device ID: ${this.deviceId}`);else return i.error("[FRONTEND WS] Cannot connect - no device ID available from DeviceRegistrationService"),!1}if(t)this.sessionId=t,i.debug(`[FRONTEND WS] 🔐 Session ID updated: ${t}`);else return i.error("[FRONTEND WS] ❌ No sessionId provided! Connection will fail."),!1;if(!this.deviceId)return i.error("[FRONTEND WS] Cannot connect - no device ID set"),!1;if(this.isConversationActive=!0,this.isConnected)return i.debug("[FRONTEND WS] Already connected for conversation"),!0;i.debug("[FRONTEND WS] Connecting for new conversation with deviceId_sessionId composite key"),this.connect(e);let s=await this.waitForConnection(3e4);return s?i.debug("[FRONTEND WS] Connected for conversation with secure composite key"):(i.debug("[FRONTEND WS] Failed to connect for conversation"),this.isConversationActive=!1),s}disconnectAfterConversation(){i.debug("[FRONTEND WS] Conversation ended, disconnecting immediately"),this.isConversationActive=!1,this.terminateAllRunningProcesses(),this.activeWebViewURLs=[],i.debug("[FRONTEND WS] Cleared active WebView URLs"),this.disconnect()}handleConversationComplete(){i.debug("[FRONTEND WS] Conversation completed, scheduling disconnect"),this.disconnectAfterConversation()}connect(e){if(this.isConnected||this.isConnecting){i.debug("[FRONTEND WS] Already connected or connecting");return}i.debug("[FRONTEND WS] === CONNECTION ATTEMPT ==="),i.debug(`[FRONTEND WS] Current state - Connected: ${this.isConnected}, Connecting: ${this.isConnecting}`),this.isConnecting=!0,this.connectionError=null;try{if(!this.sessionId){i.error("[FRONTEND WS] ❌ CRITICAL: No sessionId available for WebSocket URL!"),this.isConnecting=!1;return}let t=`wss://${this.serverHost}/frontend-tools?deviceId=${encodeURIComponent(this.deviceId||"")}&sessionId=${encodeURIComponent(this.sessionId)}`;i.debug(`[FRONTEND WS] Attempting connection to ${t}`),i.debug(`[FRONTEND WS] Device ID: ${this.deviceId||"not set"}`),i.debug(`[FRONTEND WS] Session ID: ${this.sessionId}`),i.debug(`[FRONTEND WS] User ID: ${e||this.userId||"anonymous"}`),this.webSocket=new an(t,{headers:{"User-Agent":"SnowX-CLI/1.0.1 (direct-websocket)"},protocolVersion:13,handshakeTimeout:3e4,perMessageDeflate:!1}),this.setupWebSocketHandlers()}catch(t){i.debug(`[FRONTEND WS] Connection failed: ${t.message}`),this.connectionError=t.message,this.isConnecting=!1,this.emit("connectionFailed",t)}}disconnect(){i.debug("[FRONTEND WS] === DISCONNECTING WEBSOCKET ==="),i.debug(`[FRONTEND WS] Current state - Connected: ${this.isConnected}, Connecting: ${this.isConnecting}`),this.stopHeartbeat(),this.webSocket&&(this.webSocket.close(),this.webSocket=null),this.isConnected=!1,this.isConnecting=!1,this.connectionError=null,i.debug("[FRONTEND WS] Disconnected successfully"),this.emit("disconnected")}async waitForConnection(e){return new Promise(t=>{if(this.isConnected){t(!0);return}let s=setTimeout(()=>{t(!1)},e),o=()=>{clearTimeout(s),this.off("connected",o),this.off("connectionFailed",n),t(!0)},n=()=>{clearTimeout(s),this.off("connected",o),this.off("connectionFailed",n),t(!1)};this.once("connected",o),this.once("connectionFailed",n)})}setupWebSocketHandlers(){this.webSocket&&(this.webSocket.on("open",()=>{i.debug("[FRONTEND WS] === CONNECTION OPENED ==="),i.debug(`[FRONTEND WS] WebSocket successfully connected to ${this.serverHost}`),i.debug(`[FRONTEND WS] Device ID: ${this.deviceId}`),this.isConnected=!0,this.isConnecting=!1,this.connectionError=null,this.startHeartbeat(),setTimeout(()=>{this.registerDevice()},1e3),this.emit("connected")}),this.webSocket.on("close",(e,t)=>{i.debug("[FRONTEND WS] === CONNECTION CLOSED ==="),i.debug(`[FRONTEND WS] Close code: ${e}`),i.debug(`[FRONTEND WS] Close reason: ${t}`),i.debug(`[FRONTEND WS] Was connected: ${this.isConnected}`),i.debug(`[FRONTEND WS] Conversation active: ${this.isConversationActive}`),this.isConnected=!1,this.isConnecting=!1,this.stopHeartbeat(),this.emit("disconnected")}),this.webSocket.on("error",e=>{i.debug("[FRONTEND WS] === WEBSOCKET ERROR ==="),i.debug(`[FRONTEND WS] Error: ${e.message}`),i.debug("[FRONTEND WS] Error details:",e),this.connectionError=e.message,this.isConnecting=!1,this.emit("connectionFailed",e)}),this.webSocket.on("message",e=>{try{let t=JSON.parse(e.toString());i.debug("[FRONTEND WS] === RECEIVED MESSAGE ==="),i.debug(`[FRONTEND WS] Message type: ${t.type}`),i.debug("[FRONTEND WS] Message:",JSON.stringify(t,null,2)),this.handleWebSocketMessage(t)}catch(t){i.debug(`[FRONTEND WS] Failed to parse message: ${t.message}`),i.debug("[FRONTEND WS] Raw data:",e.toString())}}))}handleWebSocketMessage(e){i.debug("[FRONTEND WS] === HANDLING MESSAGE ==="),i.debug(`[FRONTEND WS] Processing message type: ${e.type}`);let t=JSON.stringify(e),s=["prompt","instruction","system_prompt","user_prompt","template","claude","gpt","ai_model"];switch(s.some(n=>t.toLowerCase().includes(n))&&i.debug("PROMPT-BASED MESSAGE DETECTED:",{type:e.type,messageSize:t.length,promptKeywordsFound:s.filter(n=>t.toLowerCase().includes(n)),timestamp:new Date().toISOString()}),e.type){case"connection_established":i.debug("[FRONTEND WS] Connection established by server"),this.handleConnectionEstablished(e);break;case"tool_execution_request":i.debug("[FRONTEND WS] Tool execution request received"),this.handleToolExecutionRequest(e);break;case"stop_signal":i.debug("[FRONTEND WS] Stop signal received"),this.handleStopSignal(e);break;case"stop_all_tools":i.debug("[FRONTEND WS] Stop all tools signal received"),this.handleStopAllTools(e);break;case"checkpoint_request":i.debug("[FRONTEND WS] Checkpoint request received"),this.handleCheckpointRequest(e);break;case"shell_cleanup":i.debug("[FRONTEND WS] Shell cleanup signal received"),this.handleShellCleanup(e.data);break;case"ping":i.debug("[FRONTEND WS] Ping received, sending pong"),this.handlePing();break;case"pong":i.debug("[FRONTEND WS] Heartbeat pong received");break;default:i.debug(`[FRONTEND WS] Unknown message type: ${e.type}`),i.debug("[FRONTEND WS] Full message:",e)}}async handleToolExecutionRequest(e){let{data:t,metadata:s}=e,{id:o,tool_name:n,arguments:r}=t;i.debug("[FRONTEND WS] === EXECUTING TOOL ==="),i.debug(`[FRONTEND WS] Tool name: ${n}`),i.debug(`[FRONTEND WS] Tool ID: ${o}`),i.debug(`[FRONTEND WS] Tool call ID: ${s?.tool_call_id}`),i.debug("[FRONTEND WS] Arguments:",JSON.stringify(r,null,2)),i.debug(`[FRONTEND WS] Connection status: ${this.isConnected?"CONNECTED":"DISCONNECTED"}`);let a=JSON.stringify(r),l=JSON.stringify(e),u=["prompt","instruction","system_prompt","user_prompt","template","claude","gpt","execute_model","ai_model","completion"];u.some(m=>a.toLowerCase().includes(m)||l.toLowerCase().includes(m))&&i.debug("SUSPICIOUS TOOL EXECUTION DETECTED:",{toolName:n,toolId:o,promptKeywordsFound:u.filter(m=>a.toLowerCase().includes(m)||l.toLowerCase().includes(m)),argsSize:a.length,timestamp:new Date().toISOString()}),["execute_prompt","run_ai","claude_execute","gpt_run","ai_completion","prompt_exec"].includes(n.toLowerCase())&&i.debug("SUSPICIOUS TOOL NAME DETECTED:",{toolName:n,toolId:o,timestamp:new Date().toISOString()});try{let m,b=!0,S,p=new tt(this.userId,this.sessionId,s?.tool_call_id||o,this.runningProcesses,this.activeWebViewURLs);try{m=await this.toolRegistry.executeTool(n,o,r,p),i.debug(`[FRONTEND WS] Tool executed successfully via registry: ${n}`)}catch(f){i.debug(`[FRONTEND WS] Tool execution failed: ${f.message}`),m=[{type:"text",text:`Error: ${f.message}`}],b=!1,S=f.message}let v={type:"tool_execution_response",data:{id:o,tool_call_id:s?.tool_call_id||o,tool_name:n,content:m,success:b,error:S}};i.debug("[FRONTEND WS] === SENDING TOOL RESPONSE ==="),i.debug(`[FRONTEND WS] Tool: ${n}`),i.debug(`[FRONTEND WS] Success: ${b}`),i.debug(`[FRONTEND WS] Response length: ${m.length} blocks`),i.debug(`[FRONTEND WS] Connection status before send: ${this.isConnected?"CONNECTED":"DISCONNECTED"}`),this.sendMessage(v),this.emit("tool_completed",{toolName:n,toolId:o,result:m.map(f=>f.text||"").join(`
|
|
174
|
-
`),success:
|
|
175
|
-
Error Code: ${m.code}`),m.errno&&(
|
|
176
|
-
Errno: ${m.errno}`),m.syscall&&(
|
|
177
|
-
System Call: ${m.syscall}`),m.path&&(
|
|
178
|
-
Path: ${m.path}`),m.stack&&(
|
|
167
|
+
• Running the command with verbose flags for more details`:o}}});var Qe,rs=F(()=>{"use strict";U();Qe=class{toolNames=["grep","Grep"];async execute(e,t,s,o){let n=s.pattern,r=s.output_mode||"files_with_matches",a=s.path||process.cwd(),l=s.glob,u=s.type,g=s["-i"]===!0,h=s["-n"]===!0,m=s["-A"],S=s["-B"],w=s["-C"],p=s.multiline===!0,v=s.head_limit;if(!n)throw new Error("Missing pattern argument");if(n.trim().length===0)throw new Error("Pattern cannot be empty");i.debug(`[GrepTool] Grep search: pattern="${n}", path="${a}", output_mode="${r}"`);try{let{exec:f}=await import("child_process"),{promisify:I}=await import("util"),P=I(f),D="rg",C=!0;try{await P("which rg")}catch{i.debug("[GrepTool] ripgrep not found, falling back to grep"),D="grep -r",C=!1}if(C){switch(g&&(D+=" -i"),h&&(D+=" -n"),r){case"files_with_matches":D+=" -l";break;case"count":D+=" -c";break;case"content":default:break}w!==void 0?D+=` -C ${w}`:(m!==void 0&&(D+=` -A ${m}`),S!==void 0&&(D+=` -B ${S}`)),p&&(D+=" -U --multiline-dotall"),D+=` "${n.replace(/"/g,'\\"')}"`,l&&(D+=` --glob="${l}"`),u&&(D+=` --type=${u}`),D+=` "${a}"`}else{switch(g&&(D+=" -i"),h&&(D+=" -n"),r){case"files_with_matches":D+=" -l";break;case"count":D+=" -c";break}w!==void 0?D+=` -C ${w}`:(m!==void 0&&(D+=` -A ${m}`),S!==void 0&&(D+=` -B ${S}`)),D+=` "${n.replace(/"/g,'\\"')}"`,l&&(D+=` --include="${l}"`),D+=` "${a}"`}v!==void 0&&v>0&&(D+=` | head -n ${v}`),i.debug(`[GrepTool] Executing: ${D}`);let{stdout:E,stderr:_}=await P(D,{maxBuffer:10*1024*1024});if(!E&&!_)return[{type:"text",text:"No matches found"}];let A=E||_;if(r==="content"&&A){let k=`
|
|
168
|
+
|
|
169
|
+
[Found ${A.trim().split(`
|
|
170
|
+
`).length} matching line(s)]`;return[{type:"text",text:A+k}]}return[{type:"text",text:A}]}catch(f){return f.code===1?[{type:"text",text:"No matches found"}]:(i.debug(`[GrepTool] Grep failed: ${f.message}`),f.message.includes("No such file or directory")?[{type:"text",text:`Error: Search path does not exist: ${a}`}]:[{type:"text",text:"Grep search completed with no results"}])}}}});var Ke,as=F(()=>{"use strict";U();Ke=class{toolNames=["glob","Glob"];async execute(e,t,s,o){let n=s.pattern,r=s.path||process.cwd();if(!n)throw new Error("Missing pattern argument");i.debug(`[GlobTool] Glob search: pattern="${n}", path="${r}"`);try{let{exec:a}=await import("child_process"),{promisify:l}=await import("util"),u=l(a),g=n.replace(/\*\*/g,"*"),h=process.platform==="win32"?`dir /s /b "${r}\\${g}"`:`find "${r}" -name "${g}" 2>/dev/null`,{stdout:m}=await u(h);if(!m||m.trim().length===0)return[{type:"text",text:"No files found matching pattern"}];let S=m.trim().split(`
|
|
171
|
+
`);return[{type:"text",text:`Found ${S.length} file(s):
|
|
172
|
+
${S.join(`
|
|
173
|
+
`)}`}]}catch(a){return i.debug(`[GlobTool] Glob failed: ${a.message}`),[{type:"text",text:"No files found matching pattern"}]}}}});var Je,cs=F(()=>{"use strict";U();Je=class{toolNames=["open_url"];async execute(e,t,s,o){let n=s.url;if(!n)throw new Error("Missing url argument");i.debug(`[OpenUrlTool] Opening URL: ${n}`),o.activeWebViewURLs.includes(n)||(o.activeWebViewURLs.push(n),i.debug(`[OpenUrlTool] Added to active URLs: ${n}`));try{let{exec:r}=await import("child_process"),a=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";return r(`${a} "${n}"`,l=>{l?i.debug(`[OpenUrlTool] Failed to open URL in browser: ${l.message}`):i.debug(`[OpenUrlTool] URL opened in default browser: ${n}`)}),[{type:"text",text:`✅ URL opened in default browser: ${n}`}]}catch(r){return i.debug(`[OpenUrlTool] Failed to open URL: ${r.message}`),[{type:"text",text:`❌ Failed to open URL: ${r.message}`}]}}}});var Ye,ls=F(()=>{"use strict";U();Ye=class{toolNames=["manage_device_knowledge"];async execute(e,t,s,o){let n=s.action;return i.debug(`[ManageDeviceKnowledgeTool] Device knowledge management not implemented: ${n}`),[{type:"text",text:`Device knowledge management not available in CLI version: ${n}`}]}}});var Ze,us=F(()=>{"use strict";U();Ze=class{toolNames=["operator_status"];async execute(e,t,s,o){let n=s.taskId,r=s.status,a=s.message;return i.debug(`[OperatorStatusTool] Operator status - Task ${n}: ${r} - ${a}`),[{type:"text",text:"Operator status updated successfully"}]}}});var et,ds=F(()=>{"use strict";U();et=class{toolNames=["provide_input"];async execute(e,t,s,o){let n=s.input;if(!n)throw new Error("Missing input argument");i.debug(`[ProvideInputTool] Delegating provide_input to backend: ${n.substring(0,20)}...`);try{let r=(await Promise.resolve().then(()=>(ze(),yt))).ToolCallingService.getInstance(),a={id:`provide_input_${Date.now()}`,type:"function",function:{name:"provide_input",arguments:JSON.stringify({input:n})}},l=await r.executeTool(a);return l.success?[{type:"text",text:l.result?.message||"Input provided successfully"}]:[{type:"text",text:`Error: ${l.error||"Failed to provide input"}`}]}catch(r){return i.debug(`[ProvideInputTool] Failed to delegate provide_input: ${r.message}`),[{type:"text",text:`Error: ${r.message}`}]}}}});function ps(c){c.register(new Ge),c.register(new qe),c.register(new Xe),c.register(new He),c.register(new Ve),c.register(new je),c.register(new Qe),c.register(new Ke),c.register(new Je),c.register(new Ye),c.register(new Ze),c.register(new et)}var gs=F(()=>{"use strict";Kt();Jt();Yt();Zt();es();is();rs();as();cs();ls();us();ds()});var tt,ms=F(()=>{"use strict";tt=class{constructor(e,t,s,o,n){this.userId=e;this.sessionId=t;this.toolCallId=s;this.runningProcesses=o;this.activeWebViewURLs=n}}});var hs={};te(hs,{FrontendWebSocketService:()=>V});import{EventEmitter as rn}from"events";import an from"ws";var V,Fe=F(()=>{"use strict";U();de();se();Le();jt();gs();ms();V=class c extends rn{static instance;webSocket=null;serverHost;deviceId=null;userId=null;sessionId=null;deviceRegistrationService;authService;toolRegistry;isConnected=!1;connectionError=null;isConnecting=!1;runningProcesses=new Map;activeWebViewURLs=[];isConversationActive=!1;heartbeatTimer=null;constructor(e="ws.snowx.ai",t,s="node"){super(),this.serverHost=e,this.userId=t||null,this.deviceRegistrationService=ne.getInstance(),this.authService=q.getInstance(),this.deviceId=this.generateUniqueDeviceId(t,s),this.toolRegistry=new Be,ps(this.toolRegistry),i.debug("[FRONTEND WS] Tool registry initialized with 11 frontend tools"),this.deviceId?i.debug(`[FRONTEND WS] Client initialized - Using consistent Device ID: ${this.deviceId}`):i.warn("[FRONTEND WS] Client initialized without device ID - will be set on authentication")}static getInstance(){return c.instance||(c.instance=new c),c.instance}generateUniqueDeviceId(e,t="node"){if(e){let s=this.deviceRegistrationService.getCurrentDeviceId();if(s)return s}return i.warn("[FRONTEND WS] No device ID available from DeviceRegistrationService"),null}async connectForConversation(e,t){if(e&&e!==this.userId&&(this.userId=e),this.userId){let o=this.generateUniqueDeviceId(this.userId,"node");if(o&&this.deviceId!==o)i.debug(`[FRONTEND WS] Device ID changed from ${this.deviceId} to ${o} (using consistent ID from DeviceRegistrationService)`),this.deviceId=o;else if(o)i.debug(`[FRONTEND WS] Using existing consistent device ID: ${this.deviceId}`);else return i.error("[FRONTEND WS] Cannot connect - no device ID available from DeviceRegistrationService"),!1}if(t)this.sessionId=t,i.debug(`[FRONTEND WS] 🔐 Session ID updated: ${t}`);else return i.error("[FRONTEND WS] ❌ No sessionId provided! Connection will fail."),!1;if(!this.deviceId)return i.error("[FRONTEND WS] Cannot connect - no device ID set"),!1;if(this.isConversationActive=!0,this.isConnected)return i.debug("[FRONTEND WS] Already connected for conversation"),!0;i.debug("[FRONTEND WS] Connecting for new conversation with deviceId_sessionId composite key"),this.connect(e);let s=await this.waitForConnection(3e4);return s?i.debug("[FRONTEND WS] Connected for conversation with secure composite key"):(i.debug("[FRONTEND WS] Failed to connect for conversation"),this.isConversationActive=!1),s}disconnectAfterConversation(){i.debug("[FRONTEND WS] Conversation ended, disconnecting immediately"),this.isConversationActive=!1,this.terminateAllRunningProcesses(),this.activeWebViewURLs=[],i.debug("[FRONTEND WS] Cleared active WebView URLs"),this.disconnect()}handleConversationComplete(){i.debug("[FRONTEND WS] Conversation completed, scheduling disconnect"),this.disconnectAfterConversation()}connect(e){if(this.isConnected||this.isConnecting){i.debug("[FRONTEND WS] Already connected or connecting");return}i.debug("[FRONTEND WS] === CONNECTION ATTEMPT ==="),i.debug(`[FRONTEND WS] Current state - Connected: ${this.isConnected}, Connecting: ${this.isConnecting}`),this.isConnecting=!0,this.connectionError=null;try{if(!this.sessionId){i.error("[FRONTEND WS] ❌ CRITICAL: No sessionId available for WebSocket URL!"),this.isConnecting=!1;return}let t=`wss://${this.serverHost}/frontend-tools?deviceId=${encodeURIComponent(this.deviceId||"")}&sessionId=${encodeURIComponent(this.sessionId)}`;i.debug(`[FRONTEND WS] Attempting connection to ${t}`),i.debug(`[FRONTEND WS] Device ID: ${this.deviceId||"not set"}`),i.debug(`[FRONTEND WS] Session ID: ${this.sessionId}`),i.debug(`[FRONTEND WS] User ID: ${e||this.userId||"anonymous"}`),this.webSocket=new an(t,{headers:{"User-Agent":"SnowX-CLI/1.0.1 (direct-websocket)"},protocolVersion:13,handshakeTimeout:3e4,perMessageDeflate:!1}),this.setupWebSocketHandlers()}catch(t){i.debug(`[FRONTEND WS] Connection failed: ${t.message}`),this.connectionError=t.message,this.isConnecting=!1,this.emit("connectionFailed",t)}}disconnect(){i.debug("[FRONTEND WS] === DISCONNECTING WEBSOCKET ==="),i.debug(`[FRONTEND WS] Current state - Connected: ${this.isConnected}, Connecting: ${this.isConnecting}`),this.stopHeartbeat(),this.webSocket&&(this.webSocket.close(),this.webSocket=null),this.isConnected=!1,this.isConnecting=!1,this.connectionError=null,i.debug("[FRONTEND WS] Disconnected successfully"),this.emit("disconnected")}async waitForConnection(e){return new Promise(t=>{if(this.isConnected){t(!0);return}let s=setTimeout(()=>{t(!1)},e),o=()=>{clearTimeout(s),this.off("connected",o),this.off("connectionFailed",n),t(!0)},n=()=>{clearTimeout(s),this.off("connected",o),this.off("connectionFailed",n),t(!1)};this.once("connected",o),this.once("connectionFailed",n)})}setupWebSocketHandlers(){this.webSocket&&(this.webSocket.on("open",()=>{i.debug("[FRONTEND WS] === CONNECTION OPENED ==="),i.debug(`[FRONTEND WS] WebSocket successfully connected to ${this.serverHost}`),i.debug(`[FRONTEND WS] Device ID: ${this.deviceId}`),this.isConnected=!0,this.isConnecting=!1,this.connectionError=null,this.startHeartbeat(),setTimeout(()=>{this.registerDevice()},1e3),this.emit("connected")}),this.webSocket.on("close",(e,t)=>{i.debug("[FRONTEND WS] === CONNECTION CLOSED ==="),i.debug(`[FRONTEND WS] Close code: ${e}`),i.debug(`[FRONTEND WS] Close reason: ${t}`),i.debug(`[FRONTEND WS] Was connected: ${this.isConnected}`),i.debug(`[FRONTEND WS] Conversation active: ${this.isConversationActive}`),this.isConnected=!1,this.isConnecting=!1,this.stopHeartbeat(),this.emit("disconnected")}),this.webSocket.on("error",e=>{i.debug("[FRONTEND WS] === WEBSOCKET ERROR ==="),i.debug(`[FRONTEND WS] Error: ${e.message}`),i.debug("[FRONTEND WS] Error details:",e),this.connectionError=e.message,this.isConnecting=!1,this.emit("connectionFailed",e)}),this.webSocket.on("message",e=>{try{let t=JSON.parse(e.toString());i.debug("[FRONTEND WS] === RECEIVED MESSAGE ==="),i.debug(`[FRONTEND WS] Message type: ${t.type}`),i.debug("[FRONTEND WS] Message:",JSON.stringify(t,null,2)),this.handleWebSocketMessage(t)}catch(t){i.debug(`[FRONTEND WS] Failed to parse message: ${t.message}`),i.debug("[FRONTEND WS] Raw data:",e.toString())}}))}handleWebSocketMessage(e){i.debug("[FRONTEND WS] === HANDLING MESSAGE ==="),i.debug(`[FRONTEND WS] Processing message type: ${e.type}`);let t=JSON.stringify(e),s=["prompt","instruction","system_prompt","user_prompt","template","claude","gpt","ai_model"];switch(s.some(n=>t.toLowerCase().includes(n))&&i.debug("PROMPT-BASED MESSAGE DETECTED:",{type:e.type,messageSize:t.length,promptKeywordsFound:s.filter(n=>t.toLowerCase().includes(n)),timestamp:new Date().toISOString()}),e.type){case"connection_established":i.debug("[FRONTEND WS] Connection established by server"),this.handleConnectionEstablished(e);break;case"tool_execution_request":i.debug("[FRONTEND WS] Tool execution request received"),this.handleToolExecutionRequest(e);break;case"stop_signal":i.debug("[FRONTEND WS] Stop signal received"),this.handleStopSignal(e);break;case"stop_all_tools":i.debug("[FRONTEND WS] Stop all tools signal received"),this.handleStopAllTools(e);break;case"checkpoint_request":i.debug("[FRONTEND WS] Checkpoint request received"),this.handleCheckpointRequest(e);break;case"shell_cleanup":i.debug("[FRONTEND WS] Shell cleanup signal received"),this.handleShellCleanup(e.data);break;case"ping":i.debug("[FRONTEND WS] Ping received, sending pong"),this.handlePing();break;case"pong":i.debug("[FRONTEND WS] Heartbeat pong received");break;default:i.debug(`[FRONTEND WS] Unknown message type: ${e.type}`),i.debug("[FRONTEND WS] Full message:",e)}}async handleToolExecutionRequest(e){let{data:t,metadata:s}=e,{id:o,tool_name:n,arguments:r}=t;i.debug("[FRONTEND WS] === EXECUTING TOOL ==="),i.debug(`[FRONTEND WS] Tool name: ${n}`),i.debug(`[FRONTEND WS] Tool ID: ${o}`),i.debug(`[FRONTEND WS] Tool call ID: ${s?.tool_call_id}`),i.debug("[FRONTEND WS] Arguments:",JSON.stringify(r,null,2)),i.debug(`[FRONTEND WS] Connection status: ${this.isConnected?"CONNECTED":"DISCONNECTED"}`);let a=JSON.stringify(r),l=JSON.stringify(e),u=["prompt","instruction","system_prompt","user_prompt","template","claude","gpt","execute_model","ai_model","completion"];u.some(m=>a.toLowerCase().includes(m)||l.toLowerCase().includes(m))&&i.debug("SUSPICIOUS TOOL EXECUTION DETECTED:",{toolName:n,toolId:o,promptKeywordsFound:u.filter(m=>a.toLowerCase().includes(m)||l.toLowerCase().includes(m)),argsSize:a.length,timestamp:new Date().toISOString()}),["execute_prompt","run_ai","claude_execute","gpt_run","ai_completion","prompt_exec"].includes(n.toLowerCase())&&i.debug("SUSPICIOUS TOOL NAME DETECTED:",{toolName:n,toolId:o,timestamp:new Date().toISOString()});try{let m,S=!0,w,p=new tt(this.userId,this.sessionId,s?.tool_call_id||o,this.runningProcesses,this.activeWebViewURLs);try{m=await this.toolRegistry.executeTool(n,o,r,p),i.debug(`[FRONTEND WS] Tool executed successfully via registry: ${n}`)}catch(f){i.debug(`[FRONTEND WS] Tool execution failed: ${f.message}`),m=[{type:"text",text:`Error: ${f.message}`}],S=!1,w=f.message}let v={type:"tool_execution_response",data:{id:o,tool_call_id:s?.tool_call_id||o,tool_name:n,content:m,success:S,error:w}};i.debug("[FRONTEND WS] === SENDING TOOL RESPONSE ==="),i.debug(`[FRONTEND WS] Tool: ${n}`),i.debug(`[FRONTEND WS] Success: ${S}`),i.debug(`[FRONTEND WS] Response length: ${m.length} blocks`),i.debug(`[FRONTEND WS] Connection status before send: ${this.isConnected?"CONNECTED":"DISCONNECTED"}`),this.sendMessage(v),this.emit("tool_completed",{toolName:n,toolId:o,result:m.map(f=>f.text||"").join(`
|
|
174
|
+
`),success:S}),await this.captureFrontendToolResultForHistory(n,m,S,w)}catch(m){i.debug("[FRONTEND WS] === TOOL EXECUTION FAILED ==="),i.debug(`[FRONTEND WS] Tool: ${n}`),i.debug(`[FRONTEND WS] Error: ${m.message}`),i.debug("[FRONTEND WS] Error stack:",m.stack),i.debug(`[FRONTEND WS] Connection status: ${this.isConnected?"CONNECTED":"DISCONNECTED"}`);let S=`Error: ${m.message}`;m.code&&(S+=`
|
|
175
|
+
Error Code: ${m.code}`),m.errno&&(S+=`
|
|
176
|
+
Errno: ${m.errno}`),m.syscall&&(S+=`
|
|
177
|
+
System Call: ${m.syscall}`),m.path&&(S+=`
|
|
178
|
+
Path: ${m.path}`),m.stack&&(S+=`
|
|
179
179
|
|
|
180
180
|
Stack Trace:
|
|
181
|
-
${m.stack}`);let
|
|
181
|
+
${m.stack}`);let w={type:"tool_execution_response",data:{id:o,tool_call_id:s?.tool_call_id||o,tool_name:n,content:[{type:"text",text:S}],success:!1,error:m.message}};i.debug("[FRONTEND WS] Sending error response"),this.sendMessage(w),this.emit("tool_completed",{toolName:n,toolId:o,result:S,success:!1,error:m.message}),await this.captureFrontendToolResultForHistory(n,[{type:"text",text:S}],!1,m.message)}}terminateAllRunningProcesses(){i.debug(`[FRONTEND WS] Terminating ${this.runningProcesses.size} running processes`);for(let[e,t]of this.runningProcesses)try{t.kill("SIGTERM"),i.debug(`[FRONTEND WS] Terminated process for tool: ${e}`)}catch(s){i.debug(`[FRONTEND WS] Failed to terminate process ${e}: ${s.message}`)}this.runningProcesses.clear()}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.isConnected&&this.sendMessage({type:"pong",timestamp:Date.now()})},3e4)}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null)}handleConnectionEstablished(e){i.debug("[FRONTEND WS] Connection established by server"),this.registerDevice()}handleStopSignal(e){let s=e.data?.type;switch(i.debug(`[FRONTEND WS] Received stop signal: ${s}`),s){case"all":this.handleStopAll();break;case"tools":this.handleStopTools();break;default:i.debug(`[FRONTEND WS] Unknown stop type: ${s}`)}}handleStopAllTools(e){let t=e.user_id||"unknown",s=e.reason||"backend_stop_request";i.debug(`[FRONTEND WS] Stopping all tools for user: ${t}, reason: ${s}`),this.terminateAllRunningProcesses()}handleCheckpointRequest(e){i.debug("[FRONTEND WS] Handling checkpoint request");let{data:t}=e;if(!t){i.error("[FRONTEND WS] Missing data in checkpoint request");return}let{checkpoint_id:s,session_id:o}=t;if(!s||!o){i.error("[FRONTEND WS] Missing required checkpoint fields");return}i.debug(`[FRONTEND WS] Checkpoint ID: ${s}, Session ID: ${o}`);let n=he.getInstance(),r=n.getQueuedMessages(),a=r.map(g=>({content:g.content,timestamp:Math.floor(g.timestamp.getTime())})),l=a.length>0;i.debug(`[FRONTEND WS] Sending checkpoint response - Has feedback: ${l}, Count: ${a.length}`);let u={type:"checkpoint_response",data:{checkpoint_id:s,session_id:o,has_feedback:l,feedback:a}};this.sendMessage(u),l&&(i.info(`⚡ Sent ${a.length} feedback message(s) to AI`),this.emit("feedback:sent",r),n.clearQueue())}handleShellCleanup(e){i.debug("[FRONTEND WS] Received shell_cleanup signal from backend");let t=e?.sessionId;if(!t||typeof t!="string"){i.info('[FRONTEND WS] Shell cleanup received but no sessionId provided - ignoring (only "new" mode is supported, no cleanup needed)');return}i.debug(`[FRONTEND WS] Processing shell cleanup for session: ${t}`),i.info(`[FRONTEND WS] Session cleanup not needed for 'new' mode (session: ${t})`)}handleStopAll(){i.debug("[FRONTEND WS] Stopping all operations"),this.terminateAllRunningProcesses()}handleStopTools(){i.debug("[FRONTEND WS] Stopping running tools"),this.terminateAllRunningProcesses()}handlePing(){this.sendMessage({type:"pong",timestamp:Date.now()})}async registerSession(e,t){if(!this.isConnected){i.debug("[FRONTEND WS] Not connected, cannot register session");return}i.debug(`[FRONTEND WS] Registering session: ${e}`);let s={type:"register",traceId:e,userId:t||this.userId||"",deviceId:this.deviceId||"",timestamp:new Date().toISOString()};this.sendMessage(s),i.debug(`[FRONTEND WS] Session registered: ${e}`)}registerDevice(){let e={type:"device_registration",data:{deviceId:this.deviceId||"",userId:this.userId||"",deviceType:"node-cli",timestamp:new Date().toISOString()}};this.sendMessage(e),i.debug("[FRONTEND WS] Device registration sent")}sendMessage(e){if(i.debug("[FRONTEND WS] === SENDING MESSAGE ==="),i.debug(`[FRONTEND WS] Message type: ${e.type}`),i.debug(`[FRONTEND WS] WebSocket exists: ${!!this.webSocket}`),i.debug(`[FRONTEND WS] Is connected: ${this.isConnected}`),!this.webSocket||!this.isConnected){i.debug("[FRONTEND WS] ❌ Cannot send message - not connected"),i.debug(`[FRONTEND WS] WebSocket state: ${this.webSocket?this.webSocket.readyState:"null"}`);return}try{let t=JSON.stringify(e);i.debug(`[FRONTEND WS] Sending message (${t.length} chars):`,t.substring(0,200)+"..."),this.webSocket.send(t),i.debug("[FRONTEND WS] ✅ Message sent successfully")}catch(t){i.debug(`[FRONTEND WS] ❌ Failed to send message: ${t.message}`),i.debug(`[FRONTEND WS] WebSocket state: ${this.webSocket?this.webSocket.readyState:"null"}`)}}async sendStopSignal(e,t="all"){if(!this.isConnected){i.debug("[FRONTEND WS] Not connected, cannot send stop signal");return}let s={type:"stop_request",data:{user_id:e,stop_type:t,timestamp:new Date().toISOString()}};this.sendMessage(s),i.debug(`[FRONTEND WS] Sent stop signal for user: ${e}, type: ${t}`)}async sendToolRequest(e){if(!this.isConnected)throw i.debug("[FRONTEND WS] Not connected, cannot send tool request"),new Error("WebSocket not connected");let t={type:"tool_execution_request",data:{id:e.id,tool_name:e.tool_name,arguments:e.arguments,timeout:e.timeout},metadata:{tool_call_id:e.tool_call_id,timestamp:new Date().toISOString()}};i.debug(`[FRONTEND WS] Sending tool request: ${e.tool_name}`),i.debug(`[FRONTEND WS] Tool ID: ${e.id}`),i.debug("[FRONTEND WS] Arguments:",e.arguments),this.sendMessage(t)}get currentDeviceId(){return this.deviceId}isWebSocketConnected(){return this.isConnected}isConversationInProgress(){return this.isConversationActive&&this.isConnected}getActiveWebViewURLs(){return[...this.activeWebViewURLs]}getConnectionStatus(){return{isConnected:this.isConnected,isConnecting:this.isConnecting,error:this.connectionError,deviceId:this.deviceId,userId:this.userId}}async captureFrontendToolResultForHistory(e,t,s,o){let n=t.map(u=>u.text||"").join(`
|
|
182
182
|
`),{PersonalAgentService:r}=await Promise.resolve().then(()=>(ae(),Ee)),a=r.getInstance(),l=o?`Error: ${o}`:n;a.captureFrontendToolResult(e,l,s),i.debug(`[FRONTEND WS] Captured tool result for conversation history: ${e}`)}destroy(){i.debug("[FRONTEND WS] Destroying WebSocket service"),this.terminateAllRunningProcesses(),this.disconnect(),this.removeAllListeners()}}});var ve,fs=F(()=>{"use strict";ve=class{static remove(e){if(!e||!e.includes("<context>"))return e;let t=e,s=/<context>[\s\S]*?<\/context>/gi;return t=t.replace(s,""),t=t.replace(/\n{3,}/g,`
|
|
183
183
|
|
|
184
184
|
`),t.trim()}static hasContextBlocks(e){return e.includes("<context>")}}});var Ee={};te(Ee,{PersonalAgentService:()=>J});import{EventEmitter as cn}from"events";import Tt from"axios";import ln from"http";import un from"https";import{v4 as be}from"uuid";import oe from"fs";import $e from"path";import ke from"os";var _e,J,ae=F(()=>{"use strict";we();se();Fe();U();fs();_e=class{static classify(e){let t=e?.message?.toLowerCase()||e?.toString?.()?.toLowerCase()||"",s=e?.code;return t.includes("json")||t.includes("parsing")||t.includes("decode")||t.includes("format")||t.includes("invalid response")||t.includes("malformed")||t.includes("serialization")||t.includes("unexpected token")?"parsing":s==="ECONNREFUSED"||s==="ENOTFOUND"||s==="ETIMEDOUT"||s==="ECONNRESET"||s==="ERR_NETWORK"||t.includes("network")||t.includes("connection")||t.includes("timeout")||t.includes("unauthorized")||t.includes("authentication")||t.includes("forbidden")||s===401||s===403?"critical":"parsing"}},J=class c extends cn{static instance;authService;apiEndpoint="https://snowx.ai/api-beta/api/chat/tool-calling";httpAgent;httpsAgent;currentTodoList=null;activeWebViewURLs=[];operatorTaskState=null;currentOutput="";completeOutputWithToolResults="";currentPromptId=null;currentAbortController=null;currentModel=null;currentSessionId=null;accumulatedToolCalls=new Map;processedToolCallIds=new Set;constructor(){super(),this.authService=q.getInstance(),this.httpAgent=new ln.Agent({keepAlive:!0,timeout:36e5}),this.httpsAgent=new un.Agent({keepAlive:!0,timeout:36e5}),i.debug("[PERSONAL AGENT] HTTP agents initialized with 3600s socket inactivity timeout"),V.getInstance().on("tool_completed",t=>{this.emit("tool_completed",t)})}getAuthToken(){return this.authService.getAuthToken()?.token||"Bo1vmos7jlVT7aDYODhMxcaGc8E3"}async getFirebaseIdToken(){return await this.authService.getFirebaseIdToken()}getDeviceInfo(){let e=process.platform,t=process.arch,s=process.version;return`${e} ${s} (CLI, ${t})`}getDeviceKnowledgeInstruction(){try{let e=this.getDeviceKnowledgePath();this.migrateDeviceKnowledgeIfNeeded(e);let t="";return oe.existsSync(e)?t=oe.readFileSync(e,"utf8"):t=this.initializeDeviceKnowledge(),`Current device knowledge: ${t}
|
|
@@ -205,12 +205,12 @@ Remember to update memory about device if any new information is learned during
|
|
|
205
205
|
|
|
206
206
|
---
|
|
207
207
|
*Last updated: ${new Date().toISOString()}*
|
|
208
|
-
`;return oe.writeFileSync(e,a,"utf8"),a}catch{return"Basic device knowledge initialization failed."}}static getInstance(){return c.instance||(c.instance=new c),c.instance}async sendMessageWithToolCalling(e,t,s,o=.7,n=!0,r,a,l){this.currentPromptId=be(),this.currentOutput="",this.completeOutputWithToolResults="",this.currentModel=s;let u=l?.crossDeviceTaskId;u&&i.debug(`[PERSONAL AGENT] Executing cross-device task: ${u}`),l?.mode==="new"&&(t=[],i.debug("[PERSONAL AGENT] Starting new conversation (cross-device mode: new)")),this.accumulatedToolCalls.clear(),this.processedToolCallIds.clear();let g=r||this.authService.getUserId();i.debug("🔌 WebSocket will connect after receiving sessionId from API...");let m=(await Promise.resolve().then(()=>(de(),Ae))).DeviceRegistrationService.getInstance().getCurrentDeviceId();if(!m)throw i.error("No device ID available - device registration may have failed"),new Error("Device not registered - cannot submit prompt");let
|
|
208
|
+
`;return oe.writeFileSync(e,a,"utf8"),a}catch{return"Basic device knowledge initialization failed."}}static getInstance(){return c.instance||(c.instance=new c),c.instance}async sendMessageWithToolCalling(e,t,s,o=.7,n=!0,r,a,l){this.currentPromptId=be(),this.currentOutput="",this.completeOutputWithToolResults="",this.currentModel=s;let u=l?.crossDeviceTaskId;u&&i.debug(`[PERSONAL AGENT] Executing cross-device task: ${u}`),l?.mode==="new"&&(t=[],i.debug("[PERSONAL AGENT] Starting new conversation (cross-device mode: new)")),this.accumulatedToolCalls.clear(),this.processedToolCallIds.clear();let g=r||this.authService.getUserId();i.debug("🔌 WebSocket will connect after receiving sessionId from API...");let m=(await Promise.resolve().then(()=>(de(),Ae))).DeviceRegistrationService.getInstance().getCurrentDeviceId();if(!m)throw i.error("No device ID available - device registration may have failed"),new Error("Device not registered - cannot submit prompt");let S={user_prompt:{role:"user",content:a&&a.length>0?[{type:"text",text:e},...a.map(w=>({type:"image_url",image_url:{url:w}}))]:[{type:"text",text:e}]},user_id:this.authService.getUserId()||this.getAuthToken(),device_id:m,model:s.name,type:"on-device",device_type:this.getDeviceInfo(),device_knowledge_instruction:this.getDeviceKnowledgeInstruction()};if(l?.conversationId)S.conversationId=l.conversationId,i.debug(`[PERSONAL AGENT] Sending request with conversationId: ${l.conversationId}`),i.debug("[PERSONAL AGENT] Backend will auto-load conversation history");else if(t&&t.length>0){let w=t.map(p=>{let v,f=p;f.metadata?.toolResults?v=f.metadata.toolResults:f.originalContent?v=f.originalContent:v=typeof p.content=="string"?p.content:JSON.stringify(p.content);let I=[{type:"text",text:v}];return f.imageUrls&&f.imageUrls.length>0&&I.push(...f.imageUrls.map(P=>({type:"image_url",image_url:{url:P}}))),{role:p.role,content:I}});for(let p=0;p<w.length;p++)w[p].role;S.messages=w,i.debug(`[PERSONAL AGENT] Sending request with ${w.length} messages (new conversation)`)}else i.debug("[PERSONAL AGENT] Sending request (first ever prompt, no history)");return n?this.performStreamingToolCall(S):this.performNonStreamingToolCall(S)}async performStreamingToolCall(e){let t=await this.getFirebaseIdToken();return t||i.warn("[PERSONAL AGENT] ⚠️ No Firebase ID token available - request may fail with 401"),new Promise((s,o)=>{this.currentAbortController=new AbortController;let n="",r=Buffer.alloc(0),a="",l="",u=[],g=null,h=!1,m="";this.currentOutput="",this.completeOutputWithToolResults="";let S=new Map,w=new Set,p=this.authService.getUserId();Tt.post(this.apiEndpoint,e,{responseType:"stream",signal:this.currentAbortController.signal,timeout:18e6,httpAgent:this.httpAgent,httpsAgent:this.httpsAgent,headers:{"Content-Type":"application/json",Authorization:`Bearer ${t||this.getAuthToken()}`}}).then(async v=>{let f=v.data,I=v.headers["x-session-id"]||v.headers["session-id"];if(I){g=I,this.currentSessionId=I,i.debug(`[PERSONAL AGENT] 🆔 SESSION ID CAPTURED: ${I}`);let P=(await Promise.resolve().then(()=>(Fe(),hs))).FrontendWebSocketService.getInstance();i.debug("[PERSONAL AGENT] 🔌 Connecting WebSocket with sessionId..."),await P.connectForConversation(p||void 0,I)?i.debug("[PERSONAL AGENT] ✅ WebSocket connected with deviceId_sessionId composite key"):i.debug("[PERSONAL AGENT] ⚠️ WebSocket connection failed, continuing without frontend tool support")}else i.debug("[PERSONAL AGENT] ⚠️ No X-Session-Id header found in response - WebSocket will not connect");f.on("data",P=>{try{r=Buffer.concat([r,P]);let _="",A=0;for(let R=0;R<r.length;R++)try{_=r.slice(0,R+1).toString("utf8"),A=R+1}catch{break}if(A>0){let R=r.slice(0,A);r=r.slice(A),n+=R.toString("utf8")}}catch{n+=P.toString()}let D=[/\r?\n/,/\r/],C=[],E=n;C=E.split(/\r?\n/),E=C.pop()||"",n=E;for(let _ of C){let A=_.trim();if(A.startsWith("data: ")){let R=A.slice(6).trim();if(R==="[DONE]"){this.handleConversationComplete(),this.emit("BotResponseCompleted",a),s(a);return}try{let k=JSON.parse(R);if(k.type==="session_start"&&k.conversationId){let T=k.conversationId,y=k.isNewConversation||!1,$=k.title;i.debug("[PERSONAL AGENT] Received conversationId in first chunk!"),i.debug(`[PERSONAL AGENT] conversationId: ${T}`),i.debug(`[PERSONAL AGENT] isNewConversation: ${y}`),$&&i.debug(`[PERSONAL AGENT] title: "${$}"`),this.emit("conversation_id_received",{conversationId:T,isNew:y,title:$||void 0});continue}if(k.type==="title_generated"&&k.title&&k.conversationId){let T=k.title,y=k.conversationId;i.debug("[PERSONAL AGENT] Received title_generated event!"),i.debug(`[PERSONAL AGENT] conversationId: ${y}`),i.debug(`[PERSONAL AGENT] title: "${T}"`),this.emit("conversation_title_updated",{conversationId:y,title:T});continue}if(k.tool_response&&k.tool_response.content){let T=k.tool_response.content,y=k.tool_response.id||"unknown",$=k.tool_response.name||"unknown";this.emit("tool_completed",{toolName:$,toolId:y,result:T,todos:k.tool_response.todos||null}),this.emit("toolComplete",$);let x="";Array.isArray(T)?x=T.map(W=>typeof W=="string"?W:W&&typeof W=="object"&&(W.text||W.content)||"").join(""):typeof T=="string"?x=T:x=JSON.stringify(T),(!x||x.trim().length===0)&&(x="(empty tool result)");let O=`<context>
|
|
209
209
|
${x}
|
|
210
210
|
</context>`;u.push(O),a+=O+`
|
|
211
211
|
`,this.completeOutputWithToolResults+=O+`
|
|
212
212
|
`,this.currentOutput+=O+`
|
|
213
|
-
`;continue}if(k.tool_calls){i.debug("Processing tool calls:",k.tool_calls.length,"items");for(let[T,y]of k.tool_calls.entries())if(i.debug("Tool call ["+T+"]:"),y.id){i.debug("Processing tool call ID:",y.id);let $=
|
|
213
|
+
`;continue}if(k.tool_calls){i.debug("Processing tool calls:",k.tool_calls.length,"items");for(let[T,y]of k.tool_calls.entries())if(i.debug("Tool call ["+T+"]:"),y.id){i.debug("Processing tool call ID:",y.id);let $=S.get(y.id)||{};for(let[x,O]of Object.entries(y))if(x==="function"&&typeof O=="object"&&O!==null){let W=$.function||{};$.function={...W,...O}}else $[x]=O;if(S.set(y.id,$),$.function?.name&&!w.has(y.id)){let x=$.function.name;i.debug("[TOOL-DISPLAY] Showing tool call:",x,"ID:",y.id),this.emit("toolExecuting",x)}if($.function?.arguments&&$.function?.name){let x=$.function.arguments;x.endsWith("}")||x.endsWith('"}')?(i.debug("Complete tool call accumulated:",y.id,"-",$.function.name),i.debug("Arguments:",x.substring(0,100)+(x.length>100?"...":"")),w.has(y.id)||(w.add(y.id),this.handleCompleteToolCall($))):i.debug("Partial tool call:",y.id,"-",$.function.name)}}}else if(k.tool_response&&k.tool_response.content){let T=k.tool_response.content,y=k.tool_response.id||"unknown",$=k.tool_response.name||"unknown",x=k.tool_response.role||"unknown";i.debug("[PERSONAL AGENT] TOOL RESPONSE RECEIVED:"),i.debug(" Tool ID:",y),i.debug(" Tool Name:",$),i.debug(" Tool Role:",x),i.debug(" Content Length:",T.length),i.debug(" Content Preview:",T.substring(0,200)+"..."),this.emit("tool_completed",{toolName:$,toolId:y,result:T,todos:k.tool_response.todos||null}),this.emit("toolComplete",$),k.tool_response.todos&&Array.isArray(k.tool_response.todos)&&(i.debug("[PERSONAL AGENT] Tool response contains",k.tool_response.todos.length,"todo items"),this.handleTodoUpdate({items:k.tool_response.todos}));let O=`<context>
|
|
214
214
|
${T}
|
|
215
215
|
</context>`;u.push(O),a+=O+`
|
|
216
216
|
`,this.completeOutputWithToolResults+=O+`
|
|
@@ -220,7 +220,7 @@ ${K}
|
|
|
220
220
|
</context>`;if(u.push(j),a+=j+`
|
|
221
221
|
`,this.completeOutputWithToolResults+=j+`
|
|
222
222
|
`,this.currentOutput+=j+`
|
|
223
|
-
`,!$){let ee=T.match(/\{"tool_response":\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}[^}]*\}/);if(ee){let G=T.replace(ee[0],"").trim();if(G.length>0){a+=G,l+=G,this.currentOutput+=G,this.completeOutputWithToolResults+=G;let H=ve.remove(G);this.emit("data",H)}}}continue}}catch{}if(T.includes("<think>")){h=!0;let y=T.split("<think>")[0];if(y){a+=y,l+=y,this.currentOutput+=y,this.completeOutputWithToolResults+=y;let $=ve.remove(y);this.emit("data",$)}}else if(T.includes("</think>")){h=!1,m+=T.split("</think>")[0],this.emit("thinking",m),m="";let y=T.split("</think>")[1]||"";if(y){a+=y,l+=y,this.currentOutput+=y,this.completeOutputWithToolResults+=y;let $=ve.remove(y);this.emit("data",$)}}else if(h)m+=T,this.emit("thinking",m);else{a+=T,l+=T,this.currentOutput+=T,this.completeOutputWithToolResults+=T;let y=ve.remove(T);this.emit("data",y)}}else if(k.type==="todo_update")this.handleTodoUpdate(k.data);else if(k.type==="webview_update")this.handleWebViewUpdate(k.data);else if(k.type==="operator_progress")this.handleOperatorProgress(k.data);else if(k.type==="stop"){this.handleStop(k.data),s(a);return}}catch{i.debug("Treating as plain text"),a+=
|
|
223
|
+
`,!$){let ee=T.match(/\{"tool_response":\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}[^}]*\}/);if(ee){let G=T.replace(ee[0],"").trim();if(G.length>0){a+=G,l+=G,this.currentOutput+=G,this.completeOutputWithToolResults+=G;let H=ve.remove(G);this.emit("data",H)}}}continue}}catch{}if(T.includes("<think>")){h=!0;let y=T.split("<think>")[0];if(y){a+=y,l+=y,this.currentOutput+=y,this.completeOutputWithToolResults+=y;let $=ve.remove(y);this.emit("data",$)}}else if(T.includes("</think>")){h=!1,m+=T.split("</think>")[0],this.emit("thinking",m),m="";let y=T.split("</think>")[1]||"";if(y){a+=y,l+=y,this.currentOutput+=y,this.completeOutputWithToolResults+=y;let $=ve.remove(y);this.emit("data",$)}}else if(h)m+=T,this.emit("thinking",m);else{a+=T,l+=T,this.currentOutput+=T,this.completeOutputWithToolResults+=T;let y=ve.remove(T);this.emit("data",y)}}else if(k.type==="todo_update")this.handleTodoUpdate(k.data);else if(k.type==="webview_update")this.handleWebViewUpdate(k.data);else if(k.type==="operator_progress")this.handleOperatorProgress(k.data);else if(k.type==="stop"){this.handleStop(k.data),s(a);return}}catch{i.debug("Treating as plain text"),a+=R,l+=R,this.currentOutput+=R,this.completeOutputWithToolResults+=R;let T=ve.remove(R);this.emit("data",T)}}}}),f.on("end",()=>{this.emit("done"),s(a)}),f.on("error",P=>{switch(i.debug("Streaming error, disconnecting WebSocket and cleaning up"),_e.classify(P)){case"parsing":let C={type:"tool_result",tool_call_id:`error_${be()}`,error:!0,content:`Streaming parsing error occurred: ${P.message}. Please check response format and retry.`};i.debug("🔄 [PERSONAL AGENT] Parsing error returned as tool result for retry"),this.emit("tool_result",JSON.stringify(C)),V.getInstance().handleConversationComplete(),s(a);return;case"critical":V.getInstance().handleConversationComplete(),this.emit("error",P),o(P);break}})}).catch(v=>{if(v.code==="ERR_CANCELED")i.debug("Task was cancelled, disconnecting WebSocket"),V.getInstance().handleConversationComplete(),this.emit("canceled"),s(a);else switch(_e.classify(v)){case"parsing":let I={type:"tool_result",tool_call_id:`error_${be()}`,error:!0,content:`Request parsing error: ${v.message}. Please check request format and retry.`};i.debug("🔄 [PERSONAL AGENT] Request parsing error returned as tool result for retry"),this.emit("tool_result",JSON.stringify(I)),V.getInstance().handleConversationComplete(),s(a);break;case"critical":i.debug("Request failed, disconnecting WebSocket"),V.getInstance().handleConversationComplete(),o(v);break}})})}async performNonStreamingToolCall(e){try{let t=await this.getFirebaseIdToken();t||i.warn("[PERSONAL AGENT] ⚠️ No Firebase ID token available - request may fail with 401");let s=await Tt.post(this.apiEndpoint,e,{timeout:18e6,httpAgent:this.httpAgent,httpsAgent:this.httpsAgent,headers:{"Content-Type":"application/json",Authorization:`Bearer ${t||this.getAuthToken()}`}});if(s.data?.content){if(this.currentOutput=s.data.content,this.completeOutputWithToolResults=s.data.completeOutput||s.data.content,s.data.toolResults)for(let o of s.data.toolResults)this.handleToolResult(o.tool,o.result);return s.data.content}throw new Error("No response content received")}catch(t){switch(_e.classify(t)){case"parsing":let o={type:"tool_result",tool_call_id:`error_${be()}`,error:!0,content:`Non-streaming API parsing error: ${t.message}. Please check request format and retry.`};return i.debug("🔄 [PERSONAL AGENT] Non-streaming API parsing error returned as tool result for retry"),this.emit("tool_result",JSON.stringify(o)),"";case"critical":throw this.emit("error",t),new Error(`Tool calling API Error: ${t.message}`)}}}handleCompleteToolCall(e){this.emit("tool_use",e);let t=e.function?.name||"unknown",s=null;if(e.function?.arguments)try{s=JSON.parse(e.function.arguments)}catch{i.debug("[PERSONAL AGENT] Failed to parse tool arguments:",e.function.arguments);return}this.emit("toolExecuting",t),this.executeToolViaWebSocket(e.id,t,s)}async executeToolViaWebSocket(e,t,s){try{let o=V.getInstance(),n={id:e,tool_name:t,arguments:s||{},tool_call_id:e};await o.sendToolRequest(n)}catch(o){i.debug(`Failed to execute tool via WebSocket: ${o.message}`)}}handleToolResult(e,t){this.emit("tool_result",{tool:e,result:t}),i.debug(`Tool Result: ${e.name}`),t&&i.debug(` Result: ${JSON.stringify(t,null,2)}`)}handleWebSocketToolResponse(e){let{tool_name:t,content:s,success:o,error:n}=e;if(i.debug("[PERSONAL AGENT] WebSocket tool response:",t,"success:",o),o&&s){let a=`<context>
|
|
224
224
|
${s.map(l=>l.text||"").join("")}
|
|
225
225
|
</context>`;this.completeOutputWithToolResults+=a+`
|
|
226
226
|
`,this.currentOutput+=a+`
|
|
@@ -241,11 +241,11 @@ ${t}
|
|
|
241
241
|
`);if(r!==-1)o=r;else{let a=this.buffer.indexOf("\r");if(a!==-1)o=a;else return}}for(;o!==-1;){if(this.isCancelled)return;let r=this.buffer.substring(0,o);this.linesProcessed++,this.buffer.substring(o,o+2)===`\r
|
|
242
242
|
`?this.buffer=this.buffer.substring(o+2):this.buffer=this.buffer.substring(o+1);let a=r.trim();if(!a){o=this.findNextLineEnd();continue}if(a.startsWith(":")){o=this.findNextLineEnd();continue}a.startsWith("data: ")&&this.processDataLine(a,e,t,s),o=this.findNextLineEnd()}}processDataLine(e,t,s,o){if(this.isCancelled)return;this.dataLinesFound++;let n=e.substring(6).trim();if(n==="[DONE]"){this.emit("streamEnd");return}if(n)try{let r=JSON.parse(n);if(r.choices&&r.choices.length>0){let a=r.choices[0];if(a.delta.tool_calls&&a.delta.tool_calls.length>0)for(let l of a.delta.tool_calls)o?.(l);a.delta.content&&(this.contentChunksReceived++,this.processThinkingContent(a.delta.content,t,s))}}catch{}}processThinkingContent(e,t,s){if(!this.isCancelled)for(this.thinkingBuffer+=e;;)if(this.isInThinkingBlock){let o=this.thinkingBuffer.indexOf("</think>");if(o!==-1){let n=this.thinkingBuffer.substring(0,o);n&&(this.thinkingContent+=n,s?.(this.thinkingContent)),this.thinkingBuffer=this.thinkingBuffer.substring(o+8),this.isInThinkingBlock=!1;continue}this.thinkingBuffer&&(this.thinkingContent+=this.thinkingBuffer,this.thinkingBuffer="",s?.(this.thinkingContent));break}else{let o=this.thinkingBuffer.indexOf("<think>");if(o!==-1){let n=this.thinkingBuffer.substring(0,o);n&&(this.regularContent+=n,this.fullResponse+=n,t(this.regularContent)),this.thinkingBuffer=this.thinkingBuffer.substring(o+7),this.isInThinkingBlock=!0;continue}this.thinkingBuffer&&(this.regularContent+=this.thinkingBuffer,this.fullResponse+=this.thinkingBuffer,this.thinkingBuffer="",t(this.regularContent));break}}handleNonSSEResponse(e,t,s){if(this.rawDataReceived.startsWith("data: ")){let o=this.rawDataReceived.substring(6).trim();try{let n=JSON.parse(o);n.choices&&n.choices.length>0&&n.choices[0].delta.content&&this.processThinkingContent(n.choices[0].delta.content,e,t)}catch{}}else try{let o=JSON.parse(this.rawDataReceived);o.choices?.[0]?.message?.content&&this.processThinkingContent(o.choices[0].message.content,e,t)}catch{this.processThinkingContent(this.rawDataReceived,e,t)}}findNextLineEnd(){let e=this.buffer.indexOf(`\r
|
|
243
243
|
`);if(e!==-1)return e;let t=this.buffer.indexOf(`
|
|
244
|
-
`);if(t!==-1)return t;let s=this.buffer.indexOf("\r");return s!==-1?s:-1}printFinalStatistics(){this.fullResponse}cancel(){this.isCancelled=!0,this.emit("cancelled")}reset(){this.buffer="",this.fullResponse="",this.totalBytesReceived=0,this.linesProcessed=0,this.dataLinesFound=0,this.contentChunksReceived=0,this.rawDataReceived="",this.byteBuffer=Buffer.alloc(0),this.thinkingContent="",this.regularContent="",this.isInThinkingBlock=!1,this.thinkingBuffer="",this.isCancelled=!1}getStats(){return{totalBytesReceived:this.totalBytesReceived,linesProcessed:this.linesProcessed,dataLinesFound:this.dataLinesFound,contentChunksReceived:this.contentChunksReceived}}getFinalResponse(){return this.fullResponse||this.regularContent}getThinkingContent(){return this.thinkingContent}}});import Rn from"axios";import{EventEmitter as Pn}from"events";import On from"http";import Fn from"https";var rt,xs=F(()=>{"use strict";se();rt=class extends Pn{client;baseURL="https://api.snowx.io/api/portkey";currentAbortController;httpAgent;httpsAgent;constructor(){super(),this.httpAgent=new On.Agent({keepAlive:!0,timeout:36e5}),this.httpsAgent=new Fn.Agent({keepAlive:!0,timeout:36e5}),this.client=Rn.create({baseURL:this.baseURL,headers:{"Content-Type":"application/json"},timeout:36e5,httpAgent:this.httpAgent,httpsAgent:this.httpsAgent})}getAuthHeaders(){let t=q.getInstance().getAuthToken();return t?.token?{Authorization:`Bearer ${t.token}`}:{}}async executeWithRetry(e,t=3){for(let s=0;s<t;s++)try{return await e()}catch(o){if(o.response?.status===429){if(s===t-1)throw new Error("Rate limit exceeded");let n=Math.pow(2,s);await new Promise(r=>setTimeout(r,n*1e3))}else throw o}throw new Error("Max retries exceeded")}buildRequest(e,t,s,o=.7,n=.9,r,a){return{model:t.apiModelName,provider:t.provider,messages:e,stream:s,temperature:t.name.includes("o4-mini")?void 0:o,max_tokens:t.maxTokens,agent:"default",top_p:t.name.includes("o4-mini")?void 0:n,reasoning_effort:t.reasoningEffort,tools:r,tool_choice:a}}async performNonStreamingRequest(e,t,s=.7,o=.9,n,r){let a=this.buildRequest(e,t,!1,s,o,n,r);try{let u=(await this.executeWithRetry(async()=>{let{data:g}=await this.client.post("/chat/completions",a,{headers:this.getAuthHeaders()});return g})).choices[0];return{content:u.message.content||"",toolCalls:u.message.tool_calls}}catch(l){throw this.emit("error",l),new Error(`API Error: ${l.message}`)}}async performStreamingRequest(e,t,s=.7,o=.9,n,r,a,l,u){let{SnowXStreamHandlerService:g}=await Promise.resolve().then(()=>(ks(),Es)),h=this.buildRequest(e,t,!0,s,o,n,r);return new Promise((m,
|
|
244
|
+
`);if(t!==-1)return t;let s=this.buffer.indexOf("\r");return s!==-1?s:-1}printFinalStatistics(){this.fullResponse}cancel(){this.isCancelled=!0,this.emit("cancelled")}reset(){this.buffer="",this.fullResponse="",this.totalBytesReceived=0,this.linesProcessed=0,this.dataLinesFound=0,this.contentChunksReceived=0,this.rawDataReceived="",this.byteBuffer=Buffer.alloc(0),this.thinkingContent="",this.regularContent="",this.isInThinkingBlock=!1,this.thinkingBuffer="",this.isCancelled=!1}getStats(){return{totalBytesReceived:this.totalBytesReceived,linesProcessed:this.linesProcessed,dataLinesFound:this.dataLinesFound,contentChunksReceived:this.contentChunksReceived}}getFinalResponse(){return this.fullResponse||this.regularContent}getThinkingContent(){return this.thinkingContent}}});import Rn from"axios";import{EventEmitter as Pn}from"events";import On from"http";import Fn from"https";var rt,xs=F(()=>{"use strict";se();rt=class extends Pn{client;baseURL="https://api.snowx.io/api/portkey";currentAbortController;httpAgent;httpsAgent;constructor(){super(),this.httpAgent=new On.Agent({keepAlive:!0,timeout:36e5}),this.httpsAgent=new Fn.Agent({keepAlive:!0,timeout:36e5}),this.client=Rn.create({baseURL:this.baseURL,headers:{"Content-Type":"application/json"},timeout:36e5,httpAgent:this.httpAgent,httpsAgent:this.httpsAgent})}getAuthHeaders(){let t=q.getInstance().getAuthToken();return t?.token?{Authorization:`Bearer ${t.token}`}:{}}async executeWithRetry(e,t=3){for(let s=0;s<t;s++)try{return await e()}catch(o){if(o.response?.status===429){if(s===t-1)throw new Error("Rate limit exceeded");let n=Math.pow(2,s);await new Promise(r=>setTimeout(r,n*1e3))}else throw o}throw new Error("Max retries exceeded")}buildRequest(e,t,s,o=.7,n=.9,r,a){return{model:t.apiModelName,provider:t.provider,messages:e,stream:s,temperature:t.name.includes("o4-mini")?void 0:o,max_tokens:t.maxTokens,agent:"default",top_p:t.name.includes("o4-mini")?void 0:n,reasoning_effort:t.reasoningEffort,tools:r,tool_choice:a}}async performNonStreamingRequest(e,t,s=.7,o=.9,n,r){let a=this.buildRequest(e,t,!1,s,o,n,r);try{let u=(await this.executeWithRetry(async()=>{let{data:g}=await this.client.post("/chat/completions",a,{headers:this.getAuthHeaders()});return g})).choices[0];return{content:u.message.content||"",toolCalls:u.message.tool_calls}}catch(l){throw this.emit("error",l),new Error(`API Error: ${l.message}`)}}async performStreamingRequest(e,t,s=.7,o=.9,n,r,a,l,u){let{SnowXStreamHandlerService:g}=await Promise.resolve().then(()=>(ks(),Es)),h=this.buildRequest(e,t,!0,s,o,n,r);return new Promise((m,S)=>{this.currentAbortController=new AbortController;let w=[],p=new Map,v=new g;this.client.post("/chat/completions",h,{responseType:"stream",signal:this.currentAbortController.signal,headers:this.getAuthHeaders()}).then(async f=>{let I=f.data,P=f.headers["content-type"]||"",D=C=>{if(C?.index!==void 0){let E=C.index;p.has(E)||p.set(E,{});let _=p.get(E);C.id&&(_.id=C.id,_.type="function"),C.function&&(_.function||(_.function={name:"",arguments:""}),C.function.name&&(_.function.name=C.function.name),C.function.arguments&&(_.function.arguments+=C.function.arguments))}u?.(C),this.emit("tool_call_delta",C)};v.on("streamEnd",()=>{p.forEach((C,E)=>{C.id&&C.function?.name&&w.push(C)}),this.emit("done"),m({content:v.getFinalResponse(),toolCalls:w.length>0?w:void 0})}),v.on("cancelled",()=>{this.emit("canceled"),m({content:v.getFinalResponse(),toolCalls:w.length>0?w:void 0})});try{await v.processStreamingResponse(I,P,a||(()=>{}),l,D),p.forEach((C,E)=>{C.id&&C.function?.name&&w.push(C)}),this.emit("done"),m({content:v.getFinalResponse(),toolCalls:w.length>0?w:void 0})}catch(C){this.emit("error",C),S(C)}}).catch(f=>{f.code==="ERR_CANCELED"?(this.emit("canceled"),m({content:"",toolCalls:w.length>0?w:void 0})):S(f)})})}stopStreaming(){this.currentAbortController&&(this.currentAbortController.abort(),this.currentAbortController=void 0)}async testConnection(e){try{let t={role:"user",content:"Hello"};return!!(await this.performNonStreamingRequest([t],e,.7,.9)).content}catch{return!1}}}});import{io as $n}from"socket.io-client";import{EventEmitter as _n}from"events";var at,Is=F(()=>{"use strict";de();at=class c extends _n{static instance;socket=null;isConnected=!1;reconnectAttempts=0;maxReconnectAttempts=5;reconnectTimeout=null;userId=null;deviceId=null;deviceRegistrationService;constructor(){super(),this.deviceRegistrationService=ne.getInstance()}static getInstance(){return c.instance||(c.instance=new c),c.instance}async connect(e,t="https://snowx.ai"){let s=new Error().stack,o=s?.split(`
|
|
245
245
|
`)[2]?.trim()||"unknown caller";if(console.log("🔌 [WebSocket] === MAIN WEBSOCKET CONNECTION INITIATED ==="),console.log("🔌 [WebSocket] Called from:",o),console.log("🔌 [WebSocket] Call timestamp:",new Date().toISOString()),console.log("🔌 [WebSocket] Input userId:",e),console.log("🔌 [WebSocket] Input serverUrl:",t),console.log("🔌 [WebSocket] Current state:",{isConnected:this.isConnected,reconnectAttempts:this.reconnectAttempts,currentUserId:this.userId,currentDeviceId:this.deviceId}),console.log("🔌 [WebSocket] Full call stack:"),s?.split(`
|
|
246
246
|
`).slice(1,6).forEach((n,r)=>{console.log(`🔌 [WebSocket] ${r+1}. ${n.trim()}`)}),this.isConnected)return console.log("✅ [WebSocket] Already connected, returning true"),!0;if(this.userId=e,this.deviceId=this.deviceRegistrationService.getCurrentDeviceId(),console.log("🔌 [WebSocket] DeviceId:",this.deviceId),!this.deviceId)return console.error("❌ WebSocket: No device ID available from DeviceRegistrationService"),!1;try{console.log("🔌 [WebSocket] Creating socket.io connection...");let n={transports:["websocket","polling"],autoConnect:!0,reconnection:!0,reconnectionAttempts:this.maxReconnectAttempts,reconnectionDelay:1e3,timeout:1e4,query:{userId:e,deviceId:this.deviceId,deviceType:"cli",platform:process.platform}};return console.log("🔌 [WebSocket] Connection options:",JSON.stringify(n,null,2)),this.socket=$n(t,n),this.setupEventHandlers(),new Promise((r,a)=>{let l=setTimeout(()=>{a(new Error("WebSocket connection timeout"))},1e4);this.socket?.on("connect",()=>{clearTimeout(l),this.isConnected=!0,this.reconnectAttempts=0,this.emit("connected"),r(!0)}),this.socket?.on("connect_error",u=>{clearTimeout(l),console.error("❌ WebSocket connection error:",u),a(u)})})}catch(n){return console.error("❌ Failed to connect WebSocket:",n),!1}}setupEventHandlers(){this.socket&&(this.socket.on("connect",()=>{this.isConnected=!0,this.reconnectAttempts=0,this.emit("connected"),this.registerDevice()}),this.socket.on("disconnect",e=>{this.isConnected=!1,this.emit("disconnected",e),e==="io server disconnect"&&this.attemptReconnect()}),this.socket.on("connect_error",e=>{console.error("❌ WebSocket connection error:",e),this.emit("connection_error",e),this.attemptReconnect()}),this.socket.on("reconnect",e=>{this.isConnected=!0,this.emit("reconnected",e)}),this.socket.on("reconnect_error",e=>{console.error("❌ WebSocket reconnection error:",e),this.emit("reconnection_error",e)}),this.socket.on("reconnect_failed",()=>{console.error("❌ WebSocket reconnection failed after max attempts"),this.emit("reconnection_failed")}),this.socket.on("cross_device_message",e=>{this.emit("cross_device_message",e),this.handleCrossDeviceMessage(e)}),this.socket.on("conversation_sync",e=>{this.emit("conversation_sync",e),this.handleConversationSync(e)}),this.socket.on("device_status_update",e=>{this.emit("device_status_update",e),this.handleDeviceStatusUpdate(e)}),this.socket.on("typing_indicator",e=>{this.emit("typing_indicator",e)}),this.socket.on("notification",e=>{this.emit("notification",e),this.handleNotification(e)}),this.socket.on("user_activity",e=>{this.emit("user_activity",e)}),this.socket.on("tool_execution",e=>{console.log("🔧 [WebSocket] Tool execution event:",{toolName:e.toolName,status:e.status,deviceId:e.deviceId,hasResult:!!e.result,timestamp:new Date().toISOString()}),this.emit("tool_execution",e)}),this.socket.on("operator_progress",e=>{console.log("⚙️ [WebSocket] Operator progress event:",{operatorId:e.operatorId,progress:e.progress,status:e.status,hasPromptData:!!(e.prompt||e.promptTemplate),timestamp:new Date().toISOString()}),(e.prompt||e.promptTemplate)&&console.log("🚨 [WebSocket] PROMPT-BASED OPERATOR DETECTED:",{hasPrompt:!!e.prompt,hasPromptTemplate:!!e.promptTemplate,promptPreview:(e.prompt||e.promptTemplate||"").substring(0,100)+"..."}),this.emit("operator_progress",e)}),this.socket.on("webview_update",e=>{console.log("🌐 [WebSocket] Webview update event:",{type:e.type,url:e.url,hasContent:!!e.content,timestamp:new Date().toISOString()}),this.emit("webview_update",e)}),this.socket.on("todo_update",e=>{console.log("📝 [WebSocket] Todo update event:",{action:e.action,todoId:e.todoId,hasContent:!!e.content,timestamp:new Date().toISOString()}),this.emit("todo_update",e)}))}attemptReconnect(){if(this.reconnectAttempts>=this.maxReconnectAttempts){console.error("❌ Max reconnection attempts reached");return}this.reconnectTimeout&&clearTimeout(this.reconnectTimeout);let e=Math.min(1e3*Math.pow(2,this.reconnectAttempts),3e4);this.reconnectAttempts++,this.reconnectTimeout=setTimeout(()=>{this.socket&&!this.isConnected&&this.socket.connect()},e)}registerDevice(){if(!this.deviceId){console.error("Cannot register device without device ID");return}let e={id:this.deviceId,name:"Orion CLI",type:"cli",platform:process.platform,lastSeen:new Date,isOnline:!0};this.send("register_device",e)}handleCrossDeviceMessage(e){switch(console.log("📱 [WebSocket] Cross-device message received:",{type:e.type,sourceDevice:e.sourceDevice,targetDeviceId:e.targetDeviceId,dataKeys:Object.keys(e.data||{}),timestamp:new Date().toISOString()}),e.type){case"conversation_shared":console.log("💬 [WebSocket] Conversation shared:",e.data);break;case"model_sync":console.log("🤖 [WebSocket] Model sync received:",e.data);break;case"clipboard_sync":console.log("📋 [WebSocket] Clipboard sync received:",e.data);break;default:console.log("❓ [WebSocket] Unknown cross-device message type:",e.type)}}handleConversationSync(e){console.log("🔄 [WebSocket] Conversation sync received:",{action:e.action,conversationId:e.conversationId,timestamp:e.timestamp,dataSize:JSON.stringify(e.data||{}).length,deviceSource:this.deviceId}),e.action==="update"?console.log("✏️ [WebSocket] Conversation update sync processed"):e.action==="delete"?console.log("🗑️ [WebSocket] Conversation delete sync processed"):e.action==="create"&&console.log("➕ [WebSocket] Conversation create sync processed")}handleDeviceStatusUpdate(e){console.log("📱 [WebSocket] Device status update:",{deviceId:e.deviceId,status:e.status,deviceType:e.deviceType,platform:e.platform,timestamp:new Date().toISOString()})}handleNotification(e){console.log("🔔 [WebSocket] Notification received:",{type:e.type,title:e.title,message:e.message,priority:e.priority,timestamp:new Date().toISOString()})}send(e,t){if(!this.isConnected||!this.socket){console.warn("⚠️ WebSocket not connected, message not sent:",e);return}let s={type:e,data:t,timestamp:Date.now(),userId:this.userId||void 0,deviceId:this.deviceId||void 0};console.log("📤 [WebSocket] Sending message:",{type:e,dataSize:JSON.stringify(t).length,userId:this.userId,deviceId:this.deviceId,timestamp:new Date().toISOString()}),this.socket.emit(e,s)}sendCrossDeviceMessage(e,t,s){this.send("cross_device_message",{targetDeviceId:e,messageType:t,data:s,sourceDevice:this.deviceId})}shareConversation(e,t){this.sendCrossDeviceMessage(t||null,"conversation_shared",{conversationId:e,action:"share"})}syncModel(e,t){this.sendCrossDeviceMessage(t||null,"model_sync",{model:e,action:"sync"})}sendTypingIndicator(e){this.send("typing_indicator",{isTyping:e,deviceId:this.deviceId})}syncConversation(e,t,s){this.send("conversation_sync",{conversationId:e,action:t,data:s,timestamp:Date.now()})}syncToolExecution(e,t,s){this.send("tool_execution",{toolName:e,status:t,result:s,deviceId:this.deviceId})}sendUserActivity(e){this.send("user_activity",{activity:e,timestamp:Date.now()})}isWebSocketConnected(){return this.isConnected}getDeviceId(){return this.deviceId}getConnectionStatus(){return{connected:this.isConnected,attempts:this.reconnectAttempts,maxAttempts:this.maxReconnectAttempts}}disconnect(){this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null),this.socket&&(this.socket.disconnect(),this.socket=null),this.isConnected=!1,this.emit("disconnected","manual")}destroy(){this.disconnect(),this.removeAllListeners()}}});var Ds,Ns=F(()=>{"use strict";Ds={apiKey:process.env.FIREBASE_API_KEY||"AIzaSyARpn1ypwsrIwB53shF2K0AKvHjNABcpBA",authDomain:process.env.FIREBASE_AUTH_DOMAIN||"snowx-31c33.firebaseapp.com",databaseURL:process.env.FIREBASE_DATABASE_URL||"https://snowx-31c33-default-rtdb.firebaseio.com",projectId:process.env.FIREBASE_PROJECT_ID||"snowx-31c33",storageBucket:process.env.FIREBASE_STORAGE_BUCKET||"snowx-31c33.firebasestorage.app",messagingSenderId:process.env.FIREBASE_MESSAGING_SENDER_ID||"679827069698",appId:process.env.FIREBASE_APP_ID||"1:679827069698:web:d4fd2c1c30d0b94ca04b5d",measurementId:process.env.FIREBASE_MEASUREMENT_ID||"G-1HZDCGCV7M"}});var Rs={};te(Rs,{ServiceManager:()=>We});import{EventEmitter as Mn}from"events";import{initializeApp as Wn,getApps as As}from"firebase/app";import{getAuth as Un}from"firebase/auth";var We,Ot=F(()=>{"use strict";ae();xs();se();de();Is();Fe();Dt();ze();we();U();Ns();We=class c extends Mn{static instance;initialized=!1;personalAgent;networkClient;authService;deviceRegistration;webSocketService;frontendWebSocketService;crossDeviceService;toolCalling;firebaseApp=null;firebaseAuth=null;options={enableFirebase:!0,enableWebSocket:!0,enableCrossDevice:!0,enableToolCalling:!0};constructor(){super(),this.personalAgent=J.getInstance(),this.networkClient=new rt,this.authService=q.getInstance(),this.deviceRegistration=ne.getInstance(),this.webSocketService=at.getInstance(),this.frontendWebSocketService=V.getInstance(),this.crossDeviceService=xe.getInstance(),this.toolCalling=Oe.getInstance()}static getInstance(){return c.instance||(c.instance=new c),c.instance}isInitialized(){return this.initialized}async initialize(e={}){if(!this.initialized){this.options={...this.options,...e};try{this.options.enableFirebase&&await this.initializeFirebase(),await this.initializeAuth(),this.options.enableWebSocket&&await this.initializeWebSocket(),this.options.enableCrossDevice&&this.options.enableWebSocket&&await this.initializeCrossDevice(),this.options.enableToolCalling&&await this.initializeToolCalling(),this.setupServiceConnections(),this.initialized=!0,this.emit("initialized")}catch(t){throw t}}}async initializeAuth(){await this.authService.autoAuthenticate()||console.log(`
|
|
247
247
|
⚠️ Not authenticated. Please run "orion auth login" to authenticate.`)}async initializeFirebase(){try{let e=this.options.firebaseConfig||Ds;if(As().length===0?(this.firebaseApp=Wn(e),i.debug("Firebase app initialized")):(this.firebaseApp=As()[0],i.debug("Using existing Firebase app")),this.firebaseAuth=Un(this.firebaseApp),i.debug(`Firebase Auth initialized - current user: ${this.firebaseAuth.currentUser?.uid||"none"}`),this.authService.setFirebaseAuth(this.firebaseAuth),i.debug("AuthService connected to shared Firebase Auth instance"),this.firebaseApp&&this.firebaseAuth){let{FirebaseNativeService:t}=await Promise.resolve().then(()=>(It(),Ss));t.getInstance().setFirebaseInstances(this.firebaseApp,this.firebaseAuth),i.debug("FirebaseNativeService connected to shared Firebase instances")}setTimeout(()=>{i.debug(`AuthService Firebase current user after sharing: ${this.firebaseAuth?.currentUser?.uid||"none"}`)},1e3)}catch(e){i.debug("Firebase initialization failed - using access token authentication:",e)}}async initializeWebSocket(){}async ensureWebSocketConnection(){let t=new Error().stack?.split(`
|
|
248
|
-
`)[2]?.trim()||"unknown caller";if(console.log("🎯 [SERVICE MANAGER] === WEBSOCKET CONNECTION REQUEST ==="),console.log("🎯 [SERVICE MANAGER] Called from:",t),console.log("🎯 [SERVICE MANAGER] Call timestamp:",new Date().toISOString()),console.log("🎯 [SERVICE MANAGER] Current WebSocket status:",this.webSocketService.isWebSocketConnected()),this.webSocketService.isWebSocketConnected())return console.log("✅ [SERVICE MANAGER] WebSocket already connected, returning true"),!0;let s=this.authService.getUserId();if(console.log("🎯 [SERVICE MANAGER] Retrieved userId:",s),!s)return console.warn("⚠️ [SERVICE MANAGER] No user ID available, cannot connect WebSocket"),!1;try{console.log("🎯 [SERVICE MANAGER] Calling webSocketService.connect() with userId:",s);let o=await this.webSocketService.connect(s);return console.log("🎯 [SERVICE MANAGER] WebSocket connection result:",o),!!o}catch(o){return console.log("❌ [SERVICE MANAGER] WebSocket connection failed:",o),!1}}async initializeCrossDevice(){this.crossDeviceService.enable()}async initializeToolCalling(){["web_search","calculate","get_current_time","http_request"].forEach(t=>this.toolCalling.enableTool(t))}setupServiceConnections(){this.personalAgent.on("conversation_complete",e=>{this.emit("conversation_complete",e)}),this.personalAgent.on("todo_update",e=>{this.emit("todo_update",e),this.webSocketService.isWebSocketConnected()&&this.webSocketService.send("todo_update",e)}),this.personalAgent.on("tool_use",e=>{this.emit("tool_use",e),this.options.enableToolCalling&&(this.isFrontendTool(e.name)?this.executeFrontendTool(e).then(t=>{this.emit("tool_result",{toolCall:e,result:t})}).catch(t=>{this.emit("tool_error",{toolCall:e,error:t})}):this.toolCalling.executeTool(e).then(t=>{this.emit("tool_result",{toolCall:e,result:t})}))}),this.authService.on("authenticated",e=>{this.emit("authenticated",e),this.options.enableWebSocket&&!this.webSocketService.isWebSocketConnected()&&this.initializeWebSocket()}),this.webSocketService.on("connected",()=>{this.emit("websocket_connected")}),this.webSocketService.on("cross_device_message",e=>{this.emit("cross_device_message",e)}),this.toolCalling.on("tool_execution_complete",e=>{this.emit("tool_execution_complete",e)})}async sendMessage(e,t=X[0],s={}){let{usePersonalAgent:o=!0,enableToolCalling:n=this.options.enableToolCalling,temperature:r=.7,stream:a=!0}=s;try{let l=[];if(o)return await this.personalAgent.sendMessageWithToolCalling(e,l,t,r,a,this.authService.getUserId()||void 0);{let u=n?this.toolCalling.getAvailableTools():void 0;return a?new Promise((g,h)=>{let m="";this.networkClient.on("data",
|
|
248
|
+
`)[2]?.trim()||"unknown caller";if(console.log("🎯 [SERVICE MANAGER] === WEBSOCKET CONNECTION REQUEST ==="),console.log("🎯 [SERVICE MANAGER] Called from:",t),console.log("🎯 [SERVICE MANAGER] Call timestamp:",new Date().toISOString()),console.log("🎯 [SERVICE MANAGER] Current WebSocket status:",this.webSocketService.isWebSocketConnected()),this.webSocketService.isWebSocketConnected())return console.log("✅ [SERVICE MANAGER] WebSocket already connected, returning true"),!0;let s=this.authService.getUserId();if(console.log("🎯 [SERVICE MANAGER] Retrieved userId:",s),!s)return console.warn("⚠️ [SERVICE MANAGER] No user ID available, cannot connect WebSocket"),!1;try{console.log("🎯 [SERVICE MANAGER] Calling webSocketService.connect() with userId:",s);let o=await this.webSocketService.connect(s);return console.log("🎯 [SERVICE MANAGER] WebSocket connection result:",o),!!o}catch(o){return console.log("❌ [SERVICE MANAGER] WebSocket connection failed:",o),!1}}async initializeCrossDevice(){this.crossDeviceService.enable()}async initializeToolCalling(){["web_search","calculate","get_current_time","http_request"].forEach(t=>this.toolCalling.enableTool(t))}setupServiceConnections(){this.personalAgent.on("conversation_complete",e=>{this.emit("conversation_complete",e)}),this.personalAgent.on("todo_update",e=>{this.emit("todo_update",e),this.webSocketService.isWebSocketConnected()&&this.webSocketService.send("todo_update",e)}),this.personalAgent.on("tool_use",e=>{this.emit("tool_use",e),this.options.enableToolCalling&&(this.isFrontendTool(e.name)?this.executeFrontendTool(e).then(t=>{this.emit("tool_result",{toolCall:e,result:t})}).catch(t=>{this.emit("tool_error",{toolCall:e,error:t})}):this.toolCalling.executeTool(e).then(t=>{this.emit("tool_result",{toolCall:e,result:t})}))}),this.authService.on("authenticated",e=>{this.emit("authenticated",e),this.options.enableWebSocket&&!this.webSocketService.isWebSocketConnected()&&this.initializeWebSocket()}),this.webSocketService.on("connected",()=>{this.emit("websocket_connected")}),this.webSocketService.on("cross_device_message",e=>{this.emit("cross_device_message",e)}),this.toolCalling.on("tool_execution_complete",e=>{this.emit("tool_execution_complete",e)})}async sendMessage(e,t=X[0],s={}){let{usePersonalAgent:o=!0,enableToolCalling:n=this.options.enableToolCalling,temperature:r=.7,stream:a=!0}=s;try{let l=[];if(o)return await this.personalAgent.sendMessageWithToolCalling(e,l,t,r,a,this.authService.getUserId()||void 0);{let u=n?this.toolCalling.getAvailableTools():void 0;return a?new Promise((g,h)=>{let m="";this.networkClient.on("data",S=>{m+=S}),this.networkClient.on("done",()=>{g(m)}),this.networkClient.on("error",h),this.networkClient.performStreamingRequest([...l,{role:"user",content:e}],t,r,.9,u)}):(await this.networkClient.performNonStreamingRequest([...l,{role:"user",content:e}],t,r,.9,u)).content}}catch(l){throw l}}getPersonalAgent(){return this.personalAgent}getNetworkClient(){return this.networkClient}getAuthService(){return this.authService}getDeviceRegistration(){return this.deviceRegistration}getWebSocketService(){return this.webSocketService}getCrossDeviceService(){return this.crossDeviceService}getToolCalling(){return this.toolCalling}getFrontendWebSocketService(){return this.frontendWebSocketService}isFrontendTool(e){return["run_command","bash","Bash","read","Read","write","Write","edit","Edit","grep","Grep","glob","Glob","write_file","read_file","upload_file","manage_device_knowledge","open_url","operator_status","take_screenshot"].includes(e)}async executeFrontendTool(e){let{name:t,input:s}=e;switch(t){case"bash":case"Bash":case"run_command":throw new Error("Bash/run_command execution handled directly by frontend-websocket service");case"read":case"read_file":throw new Error("Read/read_file handled directly by frontend-websocket service");case"write":case"write_file":throw new Error("Write/write_file handled directly by frontend-websocket service");case"edit":throw new Error("Edit handled directly by frontend-websocket service");case"grep":throw new Error("Grep handled directly by frontend-websocket service");case"glob":throw new Error("Glob handled directly by frontend-websocket service");case"upload_file":throw new Error("uploadFile method not implemented in FrontendWebSocketService");case"open_url":throw new Error("openURL method not implemented in FrontendWebSocketService");case"take_screenshot":throw new Error("takeScreenshot method not implemented in FrontendWebSocketService");case"operator_status":throw new Error("getOperatorStatus method not implemented in FrontendWebSocketService");case"manage_device_knowledge":throw new Error("manageDeviceKnowledge method not implemented in FrontendWebSocketService");default:throw new Error(`Unknown frontend tool: ${t}`)}}getStatus(){return{initialized:this.initialized,services:{auth:this.authService.isAuthenticated(),firebase:this.firebaseAuth!==null,websocket:this.webSocketService.isWebSocketConnected(),crossDevice:this.crossDeviceService.isEnabled(),toolCalling:this.options.enableToolCalling||!1},user:{authenticated:this.authService.isAuthenticated(),userId:this.authService.getUserId(),tier:this.authService.getCachedUserTier()}}}getAvailableModels(){return X.filter(e=>this.authService.canAccessModel(e.name))}enableService(e){switch(e){case"firebase":this.options.enableFirebase=!0,this.initialized&&this.initializeFirebase();break;case"websocket":this.options.enableWebSocket=!0,this.initialized&&this.initializeWebSocket();break;case"crossDevice":this.options.enableCrossDevice=!0,this.crossDeviceService.enable();break;case"toolCalling":this.options.enableToolCalling=!0;break}}disableService(e){switch(e){case"firebase":this.options.enableFirebase=!1;break;case"websocket":this.options.enableWebSocket=!1,this.webSocketService.disconnect();break;case"crossDevice":this.options.enableCrossDevice=!1,this.crossDeviceService.disable();break;case"toolCalling":this.options.enableToolCalling=!1;break}}async shutdown(){console.log("🛑 ServiceManager shutdown initiated...");try{console.log("⏹️ Stopping active operations..."),this.personalAgent.stopCurrentOperation(),this.options.enableToolCalling&&(console.log("🔧 Stopping all running tools..."),this.toolCalling.stopAllRunningTools?.()),console.log("🌐 Disconnecting services..."),this.webSocketService.disconnect(),this.crossDeviceService.destroy(),console.log("🚪 Signing out user..."),await this.authService.signOut(),this.initialized=!1,this.emit("shutdown"),console.log("✅ ServiceManager shutdown completed")}catch(e){console.error("❌ ServiceManager shutdown error:",e)}}async waitForDeviceRegistration(e=1e4){let t=this.deviceRegistration.getCurrentDeviceId();if(t){console.log(`✅ Device ID already available: ${t}`);return}return console.log("⏳ Waiting for device registration to complete..."),new Promise((s,o)=>{let n=setTimeout(()=>{o(new Error(`Device registration timeout after ${e}ms`))},e),r=l=>{console.log(`✅ Device registration completed: ${l.deviceId}`),clearTimeout(n),this.deviceRegistration.off("DeviceRegistrationComplete",r),s()};this.deviceRegistration.on("DeviceRegistrationComplete",r);let a=this.deviceRegistration.getCurrentDeviceId();a&&(console.log(`✅ Device ID became available: ${a}`),clearTimeout(n),this.deviceRegistration.off("DeviceRegistrationComplete",r),s())})}}});import*as Wt from"@sentry/node";Wt.init({dsn:"https://9c4a287c781d5a4ea1ab453c3b1f8198@o4510140042117120.ingest.us.sentry.io/4510140071804933",sendDefaultPii:!0,tracesSampleRate:1,environment:"production"});import{Command as zn}from"commander";import Gn from"react";import{render as qn}from"ink";se();import d,{useState as ys,useEffect as Ie,useCallback as At,useRef as kn}from"react";import{Box as N,Text as b,useInput as xn,useApp as In}from"ink";import Dn from"ink-spinner";import Ts from"ink-select-input";ae();U();import{exec as dn}from"child_process";import{promisify as pn}from"util";import*as nt from"fs/promises";import*as vs from"path";import*as bs from"os";var gn=pn(dn),st=class c{static instance;constructor(){}static getInstance(){return c.instance||(c.instance=new c),c.instance}async captureScreen(){try{let e=vs.join(bs.tmpdir(),`screenshot-${Date.now()}.jpg`),t;if(process.platform==="darwin")t=`screencapture -x -t jpg -q 0.8 "${e}"`;else if(process.platform==="linux")t=`scrot -q 80 "${e}" 2>/dev/null || gnome-screenshot -f "${e}"`;else if(process.platform==="win32")t=`powershell -Command "${`Add-Type -AssemblyName System.Windows.Forms;
|
|
249
249
|
[System.Windows.Forms.SendKeys]::SendWait('{PRTSC}');
|
|
250
250
|
Start-Sleep -Milliseconds 100;
|
|
251
251
|
$img = [System.Windows.Forms.Clipboard]::GetImage();
|
|
@@ -265,17 +265,17 @@ Type a message to start.`,timestamp:Date.now()}],input:"",isLoading:!1,loadingMe
|
|
|
265
265
|
Your intelligent AI assistant.
|
|
266
266
|
Type a message to start.`,timestamp:Date.now()}],input:"",todoList:null,conversationId:null,conversationTitleGenerated:!1}));return}if(C==="/vision"){a(E=>({...E,isVisionEnabled:!E.isVisionEnabled,messages:[...E.messages,{role:"system",content:`Vision mode ${E.isVisionEnabled?"disabled":"enabled"}`,timestamp:Date.now()}],input:""}));return}if(C==="/exit"||C==="/quit"){c();return}if(C==="/stop"){r.isLoading?(t.stopStreaming(),a(E=>({...E,isLoading:!1,messages:[...E.messages,{role:"system",content:"[STOPPED] - Task was stopped by user",timestamp:Date.now()}],input:""}))):a(E=>({...E,messages:[...E.messages,{role:"system",content:"No active task to stop",timestamp:Date.now()}],input:""}));return}if(C==="/signout"){a(E=>({...E,messages:[...E.messages,{role:"system",content:"🔄 Signing out...",timestamp:Date.now()}],input:""}));try{await e.signOut()?(a(_=>({..._,messages:[..._.messages,{role:"system",content:"✅ Successfully signed out. Goodbye!",timestamp:Date.now()}]})),setTimeout(()=>c(),1e3)):a(_=>({..._,messages:[..._.messages,{role:"system",content:"⚠️ Sign out failed. Use Ctrl+C to exit.",timestamp:Date.now()}]}))}catch(E){a(_=>({..._,messages:[..._.messages,{role:"system",content:`❌ Error: ${E.message}`,timestamp:Date.now()}]}))}return}a(E=>({...E,messages:[...E.messages,{role:"system",content:`Unknown command: ${p}
|
|
267
267
|
|
|
268
|
-
Type /help to see available commands.`,timestamp:Date.now()}],input:""}));return}if(r.isLoading){let C=s.addToQueue({content:p,imageUrls:[],attachments:[],model:r.selectedModel.name});a(C?E=>({...E,input:""}):E=>({...E,messages:[...E.messages,{role:"system",content:"⚠️ Queue is full (max 5 messages)",timestamp:Date.now()}]}));return}let v=Date.now(),f={role:"user",content:p,timestamp:v},I={role:"assistant",content:"",timestamp:v+1},P=[...r.messages,f,I];a(C=>({...C,messages:P,input:"",isLoading:!0,loadingMessage:"Processing"}));let D=P.map(C=>({role:C.role,content:C.content,timestamp:new Date(C.timestamp||Date.now()),...C.tool&&{tool:C.tool},...C.toolOutput&&{toolOutput:C.toolOutput}}));u.setDelegate({messages:D,fullConversationHistory:D,isLoading:!1,currentInput:"",selectedModel:r.selectedModel,isVisionEnabled:r.isVisionEnabled,conversationId:r.conversationId,usesCustomUI:!0,updateCurrentConversation:g});try{await u.sendMessage(p)}catch(C){a(E=>({...E,messages:[...E.messages,{role:"system",content:`Error: ${C.message}`,timestamp:Date.now()}],isLoading:!1}))}},[r.isLoading,r.isVisionEnabled,r.selectedModel,s,u,e,c]),m=At(()=>{if(!s.hasQueuedMessages())return;let p=s.processNextMessage();p&&(s.startProcessing(),h(p.content))},[s,h]);Ie(()=>{let p="",v=
|
|
268
|
+
Type /help to see available commands.`,timestamp:Date.now()}],input:""}));return}if(r.isLoading){let C=s.addToQueue({content:p,imageUrls:[],attachments:[],model:r.selectedModel.name});a(C?E=>({...E,input:""}):E=>({...E,messages:[...E.messages,{role:"system",content:"⚠️ Queue is full (max 5 messages)",timestamp:Date.now()}]}));return}let v=Date.now(),f={role:"user",content:p,timestamp:v},I={role:"assistant",content:"",timestamp:v+1},P=[...r.messages,f,I];a(C=>({...C,messages:P,input:"",isLoading:!0,loadingMessage:"Processing"}));let D=P.map(C=>({role:C.role,content:C.content,timestamp:new Date(C.timestamp||Date.now()),...C.tool&&{tool:C.tool},...C.toolOutput&&{toolOutput:C.toolOutput}}));u.setDelegate({messages:D,fullConversationHistory:D,isLoading:!1,currentInput:"",selectedModel:r.selectedModel,isVisionEnabled:r.isVisionEnabled,conversationId:r.conversationId,usesCustomUI:!0,updateCurrentConversation:g});try{await u.sendMessage(p)}catch(C){a(E=>({...E,messages:[...E.messages,{role:"system",content:`Error: ${C.message}`,timestamp:Date.now()}],isLoading:!1}))}},[r.isLoading,r.isVisionEnabled,r.selectedModel,s,u,e,c]),m=At(()=>{if(!s.hasQueuedMessages())return;let p=s.processNextMessage();p&&(s.startProcessing(),h(p.content))},[s,h]);Ie(()=>{let p="",v=A=>{a(R=>({...R,conversationId:A.conversationId,conversationTitleGenerated:!!A.title}))},f=A=>{},I=()=>{a(A=>({...A,loadingMessage:"Processing"}))},P=A=>{p+=A,a(R=>{let k=[...R.messages];for(let T=k.length-1;T>=0;T--)if(k[T].role==="assistant"){k[T].content=p;break}return{...R,messages:k}})},D=A=>{a(R=>{let k=[...R.messages];for(let T=k.length-1;T>=0;T--)if(k[T].role==="assistant"){let y=`
|
|
269
269
|
|
|
270
|
-
• ${
|
|
271
|
-
${
|
|
270
|
+
• ${A}`;k[T].content+=y,p+=y;break}return{...R,messages:k,loadingMessage:`Running ${A}`}})},C=A=>{if(A&&A.toolName&&A.result){let R="";typeof A.result=="string"?R=A.result:Array.isArray(A.result)?R=A.result.map(x=>typeof x=="string"?x:x&&typeof x=="object"?x.text||x.content||JSON.stringify(x):"").join(""):A.result.output?R=typeof A.result.output=="string"?A.result.output:JSON.stringify(A.result.output,null,2):A.result.content?R=A.result.content:R=JSON.stringify(A.result,null,2);let k=`<context>
|
|
271
|
+
${R}
|
|
272
272
|
</context>`;a(x=>{let O=[...x.messages];for(let W=O.length-1;W>=0;W--)if(O[W].role==="assistant"){let K=O[W];K.metadata||(K.metadata={});let j=K.metadata;j.toolResults?j.toolResults+=`
|
|
273
|
-
`+k:j.toolResults=k;break}return{...x,messages:O}});let T=`${
|
|
274
|
-
`),O=x.length,W=
|
|
275
|
-
`)}else T="Todo list updated",y=""}else if(ee.includes("read")){T="Read completed";let G=
|
|
273
|
+
`+k:j.toolResults=k;break}return{...x,messages:O}});let T=`${A.toolName} completed`,y="";if(R){let x=R.split(`
|
|
274
|
+
`),O=x.length,W=R.length,K=R.match(/(?:File|Path|file_path):\s*(.+?)(?:\n|$)/i)||R.match(/(?:Writing|Reading|Editing):\s*(.+?)(?:\n|$)/i),j=K?K[1].trim():null,ee=A.toolName.toLowerCase();if(ee.includes("todo")){let G=A.todos;if(G&&Array.isArray(G)&&G.length>0){let H=G.filter(le=>le.status==="completed").length,Se=G.length;T=`Tasks (${H}/${Se})`,y=G.map(le=>{let _t=le.status==="completed"?"✓":le.status==="inProgress"||le.status==="in_progress"?"⋯":"○",Mt=le.text||le.content||"Unknown task";return` ${_t} ${Mt}`}).join(`
|
|
275
|
+
`)}else T="Todo list updated",y=""}else if(ee.includes("read")){T="Read completed";let G=R.match(/Read (\d+) lines \(from line (\d+) to (\d+)\) out of (\d+) total lines\.\nFile: (.+?)\n\n/);if(G){let[,H,Se,$s,le,_t]=G;T=`Read completed (${H}/${le} lines)`,j&&(T=`Read ${j}`),y=R.substring(G[0].length)}else R.includes("more lines)")?(T="Read completed",y=R):(T=`Read completed (${O} lines)`,y=x.slice(0,5).join(`
|
|
276
276
|
`)+(O>5?`
|
|
277
277
|
...
|
|
278
|
-
(${O-5} more lines)`:""))}else if(ee.includes("write"))if(T="Write completed",
|
|
278
|
+
(${O-5} more lines)`:""))}else if(ee.includes("write"))if(T="Write completed",R.includes("more lines)")||R.includes("+ ..."))y=R;else{let G=x.filter(H=>H.startsWith("+ ")).slice(0,8);G.length>0?(y=G.join(`
|
|
279
279
|
`),x.filter(H=>H.startsWith("+ ")).length>8&&(y+=`
|
|
280
280
|
+ ...
|
|
281
281
|
|
|
@@ -283,23 +283,23 @@ ${A}
|
|
|
283
283
|
`),O>8&&(y+=`
|
|
284
284
|
+ ...
|
|
285
285
|
|
|
286
|
-
(${O-8} more lines)`))}else if(ee.includes("edit"))if(T="Edit completed",j&&(T=`Edited ${j}`),
|
|
286
|
+
(${O-8} more lines)`))}else if(ee.includes("edit"))if(T="Edit completed",j&&(T=`Edited ${j}`),R.match(/(replaced|search|->|→)/gi)){let H=x.filter(Se=>Se.toLowerCase().includes("replaced")||Se.toLowerCase().includes("search")||Se.includes("->")||Se.includes("→"));y=H.slice(0,5).join(`
|
|
287
287
|
`),H.length>5&&(y+=`
|
|
288
288
|
... (${H.length-5} more changes)`)}else y=x.slice(0,8).join(`
|
|
289
289
|
`),O>8&&(y+=`
|
|
290
|
-
... (${O-8} more lines)`);else ee.includes("bash")||ee.includes("command")?(T="Command completed",
|
|
290
|
+
... (${O-8} more lines)`);else ee.includes("bash")||ee.includes("command")?(T="Command completed",R.includes("showing first")||R.includes("more lines)")?y=R:(y=x.slice(0,15).join(`
|
|
291
291
|
`),O>15&&(y+=`
|
|
292
292
|
|
|
293
|
-
... (showing first 15 of ${O} lines)`))):(T=`${
|
|
293
|
+
... (showing first 15 of ${O} lines)`))):(T=`${A.toolName} completed`,y=x.slice(0,8).join(`
|
|
294
294
|
`),O>8&&(y+=`
|
|
295
295
|
... (${O-8} more lines)`))}let $="";y?$=`
|
|
296
296
|
${y.split(`
|
|
297
297
|
`).map((W,K)=>K===0?` └─ ${T}
|
|
298
298
|
${W}`:` ${W}`).join(`
|
|
299
299
|
`)}`:$=`
|
|
300
|
-
└─ ${T}`,a(x=>{let O=[...x.messages];for(let W=O.length-1;W>=0;W--)if(O[W].role==="assistant"){if(
|
|
301
|
-
`);return d.createElement(
|
|
302
|
-
`);return d.createElement(
|
|
300
|
+
└─ ${T}`,a(x=>{let O=[...x.messages];for(let W=O.length-1;W>=0;W--)if(O[W].role==="assistant"){if(A.toolName.toLowerCase().includes("todo")){let j=/\n\n• [Tt]odo[Ww]rite\n[\s\S]*?(?=\n\n• |\n\n▶ |$)/g;O[W].content=O[W].content.replace(j,"")}O[W].content+=$,p+=$;break}return{...x,messages:O}})}},E=()=>{p="",a(A=>({...A,isLoading:!1}))},_=A=>{a(R=>({...R,messages:[...R.messages,{role:"system",content:`Error: ${A.message||"Unknown error"}`,timestamp:Date.now()}],isLoading:!1})),p=""};return t.on("conversation_id_received",v),t.on("conversation_title_updated",f),t.on("thinking",I),t.on("data",P),t.on("toolExecuting",D),t.on("tool_completed",C),t.on("done",E),t.on("error",_),()=>{t.off("conversation_id_received",v),t.off("conversation_title_updated",f),t.off("thinking",I),t.off("data",P),t.off("toolExecuting",D),t.off("tool_completed",C),t.off("done",E),t.off("error",_)}},[t,m]),Ie(()=>{let p=P=>{a(D=>({...D,queuedMessages:P}))},v=P=>{},f=P=>{l.current=P,a(D=>({...D,todoList:P}))},I=P=>{if(r.isLoading){a(D=>D.crossDeviceQueue.length>=10?{...D,messages:[...D.messages,{role:"system",content:"⚠️ Cross-device queue is full - task rejected",timestamp:Date.now()}]}:{...D,crossDeviceQueue:[...D.crossDeviceQueue,P.prompt]});return}h(P.prompt)};return s.on("queue:updated",p),o.on("feedback:sent",v),t.on("todo_update",f),n.on("CrossDeviceTaskSendMessage",I),()=>{s.off("queue:updated",p),o.off("feedback:sent",v),t.off("todo_update",f),n.off("CrossDeviceTaskSendMessage",I)}},[s,o,t,n,h,r.isLoading,r.selectedModel.name]),Ie(()=>{!r.isLoading&&s.hasQueuedMessages()&&m()},[r.isLoading,s,m]),Ie(()=>{if(!r.isLoading&&!s.hasQueuedMessages()&&r.crossDeviceQueue.length>0){let p=r.crossDeviceQueue[0];a(v=>({...v,crossDeviceQueue:v.crossDeviceQueue.slice(1)})),h(p)}},[r.isLoading,r.crossDeviceQueue,s,h]),xn((p,v)=>{if(v.escape){if(r.isLoading){t.stopStreaming(),a(f=>({...f,isLoading:!1,messages:[...f.messages,{role:"system",content:"[STOPPED] - Task was stopped by user",timestamp:Date.now()}]}));return}if(r.showModelMenu||r.showCommandMenu){a(f=>({...f,showModelMenu:!1,showCommandMenu:!1,input:f.showCommandMenu&&f.input==="/"?"":f.input}));return}if(r.showHelp){a(f=>({...f,showHelp:!1}));return}}if(!r.showModelMenu){if(v.ctrl&&p==="c"){r.isLoading?(t.stopStreaming(),a(f=>({...f,isLoading:!1,messages:[...f.messages,{role:"system",content:"[STOPPED] - Task was stopped by user",timestamp:Date.now()}]}))):c();return}if(p==="?"&&r.input===""){a(f=>({...f,showHelp:!f.showHelp}));return}if(v.return&&!r.showCommandMenu){r.input.trim()&&h(r.input);return}if(v.delete||v.backspace){a(f=>{let I=f.input.slice(0,-1);return f.showCommandMenu&&!I.startsWith("/")?{...f,input:I,showCommandMenu:!1}:{...f,input:I}});return}!v.ctrl&&!v.meta&&p&&a(f=>{let I=f.input+p;return I==="/"&&!f.showCommandMenu?{...f,input:I,showCommandMenu:!0}:{...f,input:I}})}});let S=e.getUserEmail()||"User",w=ue.getDisplayName(ue.getCurrentUserTier());return d.createElement(N,{flexDirection:"column",width:"100%"},d.createElement(N,{borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:0,width:"100%"},d.createElement(b,{color:"white"},r.selectedModel.displayName),d.createElement(b,{color:"gray",dimColor:!0}," • "),d.createElement(b,{color:"gray"},S),d.createElement(b,{color:"gray",dimColor:!0}," • "),d.createElement(b,{color:"white"},w),r.queuedMessages.length>0&&d.createElement(d.Fragment,null,d.createElement(b,{color:"gray",dimColor:!0}," • "),d.createElement(b,{color:"white",inverse:!0,bold:!0}," ",r.queuedMessages.length," "),d.createElement(b,{color:"gray"}," queued")),r.crossDeviceQueue.length>0&&d.createElement(d.Fragment,null,d.createElement(b,{color:"gray",dimColor:!0}," • "),d.createElement(b,{color:"blue",inverse:!0,bold:!0}," 📱 ",r.crossDeviceQueue.length," "),d.createElement(b,{color:"gray"}," cross-device"))),d.createElement(N,{flexDirection:"column",paddingX:2,paddingY:1,minHeight:15},r.messages.map((p,v)=>d.createElement(Nn,{key:`${p.role}-${p.timestamp}-${v}`,message:p}))),r.todoList&&r.todoList.todos.length>0&&r.todoList.todos.some(p=>p.status!=="completed")&&d.createElement(N,{paddingX:2,marginBottom:1},d.createElement(N,{borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:1,flexDirection:"column"},d.createElement(N,{marginBottom:1},d.createElement(b,{color:"white",bold:!0},"Tasks"),d.createElement(b,{color:"gray"}," • "),d.createElement(b,{color:"gray"},r.todoList.todos.filter(p=>p.status==="completed").length,"/",r.todoList.todos.length)),r.todoList.todos.map((p,v)=>{let f=p.status==="completed"?"✓":p.status==="in_progress"?"⋯":"○",I=p.status==="completed"?"green":p.status==="in_progress"?"blue":"gray";return d.createElement(N,{key:p.id||v},d.createElement(b,{color:I},f),d.createElement(b,{color:"gray"}," "),d.createElement(b,{color:p.status==="completed"?"gray":"white",dimColor:p.status==="completed"},p.status==="in_progress"&&p.activeForm?p.activeForm:p.text))}))),r.isLoading&&d.createElement(N,{paddingX:0,marginBottom:1,flexDirection:"column"},d.createElement(N,null,d.createElement(b,{color:"magenta"},d.createElement(Dn,{type:"dots"})),d.createElement(b,{color:"white"}," ",r.loadingMessage,"… "),d.createElement(b,{color:"white"},"(esc to interrupt)")),d.createElement(N,{marginLeft:2},d.createElement(b,{color:"yellow"},"If experiencing latency: rate limit hit. Screenshot & tag @MeetOrion on X for quota help"))),r.showHelp&&d.createElement(N,{borderStyle:"round",borderColor:"white",paddingX:2,paddingY:1,flexDirection:"column"},d.createElement(b,{bold:!0,color:"white"},"Keyboard Shortcuts"),d.createElement(N,{marginTop:1,flexDirection:"column"},d.createElement(b,{color:"white"},"• ",d.createElement(b,{color:"white",bold:!0},"Enter")," ",d.createElement(b,{color:"white"},"Submit message")),d.createElement(b,{color:"white"},"• ",d.createElement(b,{color:"white",bold:!0},"?")," ",d.createElement(b,{color:"white"},"Toggle this help")),d.createElement(b,{color:"white"},"• ",d.createElement(b,{color:"white",bold:!0},"Esc")," ",d.createElement(b,{color:"white"},"Stop generation / Close menus")),d.createElement(b,{color:"white"},"• ",d.createElement(b,{color:"white",bold:!0},"Ctrl+C")," ",d.createElement(b,{color:"white"},"Stop generation / Exit"))),d.createElement(N,{marginTop:1},d.createElement(b,{color:"white"},"Press Esc to close"))),r.showModelMenu&&d.createElement(N,{borderStyle:"round",borderColor:"white",paddingX:2,paddingY:1,flexDirection:"column"},d.createElement(b,{bold:!0,color:"white"},"Select Model"),d.createElement(N,{marginTop:1},d.createElement(Ts,{items:X.map(p=>({label:`${p.displayName}`,value:p.name})),onSelect:p=>{let v=X.find(f=>f.name===p.value);v&&(pe.set("selectedAIModel",v.name),a(f=>({...f,selectedModel:v,showModelMenu:!1,messages:[...f.messages,{role:"system",content:`Switched to ${v.displayName}`,timestamp:Date.now()}]})))}})),d.createElement(N,{marginTop:1},d.createElement(b,{color:"white"},"Esc to cancel"))),r.showCommandMenu&&(()=>{let p=[{label:"/model — Change AI model",value:"model"},{label:"/new — Start new conversation",value:"new"},{label:"/clear — Clear conversation",value:"clear"},{label:"/stop — Stop current generation",value:"stop"},{label:"/vision — Toggle vision mode",value:"vision"},{label:"/signout — Sign out and exit",value:"signout"},{label:"/exit — Exit Orion",value:"exit"},{label:"/help — Show this menu",value:"help"}],v=r.input.startsWith("/")?r.input.substring(1).toLowerCase():"",f=v?p.filter(I=>I.value.toLowerCase().includes(v)):p;return d.createElement(N,{borderStyle:"round",borderColor:"white",paddingX:2,paddingY:1,flexDirection:"column"},d.createElement(b,{bold:!0,color:"white"},"Available Commands ",v&&`(filtered: "${v}")`),d.createElement(N,{marginTop:1},d.createElement(Ts,{items:f.length>0?f:[{label:"No matching commands",value:""}],onSelect:I=>{I.value&&(a(P=>({...P,showCommandMenu:!1,input:""})),h(`/${I.value}`))}})),d.createElement(N,{marginTop:1},d.createElement(b,{color:"white"},"Esc to cancel")))})(),r.queuedMessages.length>0&&d.createElement(N,{flexDirection:"column",paddingX:2,marginBottom:1},r.queuedMessages.map((p,v)=>d.createElement(N,{key:p.id,borderStyle:"round",borderColor:"white",paddingX:2,paddingY:0,marginBottom:1},d.createElement(N,null,d.createElement(b,{color:"white",bold:!0},v+1),d.createElement(b,{color:"white"}," • "),d.createElement(b,{color:"white"},p.content.length>60?p.content.substring(0,60)+"...":p.content)))),d.createElement(N,null,d.createElement(b,{color:"white"},r.queuedMessages.length," message",r.queuedMessages.length>1?"s":""," queued"))),r.crossDeviceQueue.length>0&&d.createElement(N,{flexDirection:"column",paddingX:2,marginBottom:1},r.crossDeviceQueue.map((p,v)=>d.createElement(N,{key:`cross-${v}`,borderStyle:"round",borderColor:"blue",paddingX:2,paddingY:0,marginBottom:1},d.createElement(N,null,d.createElement(b,{color:"blue",bold:!0},"📱 ",v+1),d.createElement(b,{color:"white"}," • "),d.createElement(b,{color:"white"},p.length>60?p.substring(0,60)+"...":p)))),d.createElement(N,null,d.createElement(b,{color:"blue"},r.crossDeviceQueue.length," cross-device task",r.crossDeviceQueue.length>1?"s":""," waiting"))),d.createElement(N,{borderStyle:"round",borderColor:"white",paddingX:2,paddingY:0,flexDirection:"column",width:"100%"},d.createElement(N,null,d.createElement(b,{color:"white"},"▶ "),d.createElement(b,{color:"white"},r.input,!r.isLoading&&d.createElement(b,{color:"white",inverse:!0}," "))),d.createElement(N,{marginTop:0},d.createElement(b,{color:"white"},r.isLoading?"Send feedback or press Enter to queue · esc to stop":"/help · ? · enter to submit"))),d.createElement(N,{paddingX:2,paddingY:0},d.createElement(b,{color:"white"},"? help · Ctrl+C exit")))}function Rt(c){let e=c;return e=e.replace(/\*\*(.+?)\*\*/g,"$1"),e=e.replace(/__(.+?)__/g,"$1"),e=e.replace(/\*(.+?)\*/g,"$1"),e=e.replace(/_(.+?)_/g,"$1"),e=e.replace(/`(.+?)`/g,"$1"),e=it(e),e}function Nn({message:c}){let{role:e,content:t,tool:s}=c;if(e==="system"){let o=t.split(`
|
|
301
|
+
`);return d.createElement(N,{marginBottom:1,justifyContent:"flex-start"},d.createElement(N,{paddingX:2,paddingY:1,flexDirection:"column",borderStyle:"round",borderColor:"white"},o.map((n,r)=>r===0?d.createElement(b,{key:`system-${r}-${n.substring(0,10)}`,color:"white",bold:!0},n):d.createElement(b,{key:`system-${r}-${n.substring(0,10)}`,color:"white"},n))))}if(e==="user")return d.createElement(N,{marginBottom:1},d.createElement(b,{color:"blue"}," ▶ "),d.createElement(b,{color:"white",bold:!0},t));if(e==="assistant"){let o=t.split(`
|
|
302
|
+
`);return d.createElement(N,{marginBottom:1,flexDirection:"column"},d.createElement(N,null,d.createElement(b,{color:"white"}," Orion ")),o.map((n,r)=>{if(n.match(/^• /)){let u=!1;for(let g=r-1;g>=0;g--){if(o[g].match(/^ └─ /)){u=!0;break}if(o[g].match(/^• /))break}return u?d.createElement(N,{key:r,flexDirection:"column"},d.createElement(b,null," "),d.createElement(N,null,d.createElement(b,{color:"gray"},"●"),d.createElement(b,{color:"white",bold:!0},n.substring(1)))):d.createElement(N,{key:r},d.createElement(b,{color:"gray"},"●"),d.createElement(b,{color:"white",bold:!0},n.substring(1)))}if(n.match(/^ └─ /)){let u=n.substring(4);return d.createElement(N,{key:r},d.createElement(b,{color:"green"}," └─ "),d.createElement(b,{color:"white"},u))}if(n.match(/^ [✓⋯○] /)){let u=n.substring(5,6),g=n.substring(7),h=u==="✓"?"green":u==="⋯"?"blue":"gray",m=o[r+1];return m&&(m.match(/^• /)||m.trim()!==""&&!m.match(/^ /))?d.createElement(N,{key:r,flexDirection:"column"},d.createElement(N,null,d.createElement(b,{color:h}," ",u," "),d.createElement(b,{color:u==="✓"?"gray":"white"},g)),d.createElement(b,null," ")):d.createElement(N,{key:r},d.createElement(b,{color:h}," ",u," "),d.createElement(b,{color:u==="✓"?"gray":"white"},g))}if(n.match(/^ \+ /)){let u=o[r+1];return u&&(u.match(/^• /)||u.trim()!==""&&!u.match(/^ /))?d.createElement(N,{key:r,flexDirection:"column"},d.createElement(N,null,d.createElement(b,{color:"green"}," + "),d.createElement(b,{color:"white"},n.substring(7))),d.createElement(b,null," ")):d.createElement(N,{key:r},d.createElement(b,{color:"green"}," + "),d.createElement(b,{color:"white"},n.substring(7)))}if(n.match(/^ \d+→/)){let u=n.match(/^( \d+→)(.*)$/);if(u){let g=o[r+1];return g&&(g.match(/^• /)||g.trim()!==""&&!g.match(/^ /))?d.createElement(N,{key:r,flexDirection:"column"},d.createElement(N,null,d.createElement(b,{color:"gray"},u[1]),d.createElement(b,{color:"white"},u[2])),d.createElement(b,null," ")):d.createElement(N,{key:r},d.createElement(b,{color:"gray"},u[1]),d.createElement(b,{color:"white"},u[2]))}}if(n.match(/^ /)){let u=Rt(n),g=o[r+1];return g&&(g.match(/^• /)||g.trim()!==""&&!g.match(/^ /))?d.createElement(N,{key:r,flexDirection:"column"},d.createElement(b,{color:"white"},u),d.createElement(b,null," ")):d.createElement(b,{key:r,color:"white"},u)}if(n.trim()==="")return d.createElement(b,{key:r}," ");let a=r>0?o[r-1]:null;return a&&a.match(/^ /)?d.createElement(N,{key:r,flexDirection:"column"},d.createElement(b,null," "),d.createElement(b,{color:"white"},Rt(n))):d.createElement(b,{key:r,color:"white"},Rt(n))}))}return null}Ot();se();se();import M from"chalk";import Ln from"inquirer";import Bn from"open";var ce=class{authService;constructor(){this.authService=q.getInstance()}async login(){console.log(M.blue(`
|
|
303
303
|
🔐 Orion Authentication`)),console.log(M.gray("─".repeat(50)));let e="https://meetorion.app/auth?backUrl=/auth/token&platform=cli";console.log(M.yellow(`
|
|
304
304
|
Please visit the following URL to authenticate:`)),console.log(M.cyan.underline(e));try{await Bn(e),console.log(M.gray(`
|
|
305
305
|
(Browser opened automatically)`))}catch{console.log(M.gray(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zinley/orion",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "A fully autonomous on-device agent that lives in your terminal.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -11,21 +11,9 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "node build.js",
|
|
16
|
-
"dev": "tsx watch src/index.ts",
|
|
17
|
-
"start": "node dist/index.js",
|
|
18
|
-
"demo": "tsx src/ink-ui/index.tsx",
|
|
19
|
-
"clean": "rm -rf dist",
|
|
20
|
-
"prepublishOnly": "npm run clean && npm run build",
|
|
21
|
-
"test": "npm run build && node test-task-validation.js",
|
|
22
|
-
"test:security": "npm run build && node test-security-integration.js",
|
|
23
|
-
"test:all": "npm run test && npm run test:security"
|
|
24
|
-
},
|
|
25
14
|
"keywords": [],
|
|
26
15
|
"author": "",
|
|
27
16
|
"license": "ISC",
|
|
28
|
-
"packageManager": "pnpm@10.6.2",
|
|
29
17
|
"devDependencies": {
|
|
30
18
|
"@types/figlet": "^1.7.0",
|
|
31
19
|
"@types/marked-terminal": "^6.1.1",
|
|
@@ -68,5 +56,15 @@
|
|
|
68
56
|
"terminal-link": "^5.0.0",
|
|
69
57
|
"uuid": "^13.0.0",
|
|
70
58
|
"ws": "^8.18.3"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "node build.js",
|
|
62
|
+
"dev": "tsx watch src/index.ts",
|
|
63
|
+
"start": "node dist/index.js",
|
|
64
|
+
"demo": "tsx src/ink-ui/index.tsx",
|
|
65
|
+
"clean": "rm -rf dist",
|
|
66
|
+
"test": "npm run build && node test-task-validation.js",
|
|
67
|
+
"test:security": "npm run build && node test-security-integration.js",
|
|
68
|
+
"test:all": "npm run test && npm run test:security"
|
|
71
69
|
}
|
|
72
|
-
}
|
|
70
|
+
}
|