@huyooo/ai-chat-bridge-electron 0.2.40 → 0.2.41
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/main/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ipcMain as e,shell as s}from"electron";import*as t from"fs";import*as n from"path";import{HybridAgent as r,MODELS as o,DEFAULT_MODEL as a,isThrowableToolError as c}from"@huyooo/ai-chat-core";import{createStorage as i}from"@huyooo/ai-chat-storage";import*as l from"zlib";var d=1,u=2,h=9,f=15,g=0,y=2,p=0,m=1,w=0,$=1;function b(e,s,t,n){return[17,e<<4|s,t<<4|n,0]}function S(e,s=!1,t=!0){const n=b(u,s?y:g,p,t?$:w),r=t?l.gzipSync(e):e,o=Buffer.alloc(4);return o.writeUInt32BE(r.length,0),Buffer.concat([Buffer.from(n),o,r])}import E from"ws";import{v4 as C}from"uuid";var I=class{config;ws=null;callbacks={};connectId="";isConnected=!1;sessionConfig={};constructor(e){this.config=e}getWsUrl(){return!1!==this.config.useAsyncMode?"wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async":"wss://openspeech.bytedance.com/api/v3/sauc/bigmodel"}getResourceId(){return this.config.resourceId||"volc.bigasr.sauc.duration"}connect(e,s={}){return new Promise((t,n)=>{this.callbacks=e,this.sessionConfig=s,this.connectId=C();const r=this.getWsUrl();this.ws=new E(r,{headers:{"X-Api-App-Key":this.config.appId,"X-Api-Access-Key":this.config.accessKey,"X-Api-Resource-Id":this.getResourceId(),"X-Api-Connect-Id":this.connectId}}),this.ws.on("open",()=>{this.isConnected=!0,this.sendFullClientRequest(),this.callbacks.onConnected?.(),t()}),this.ws.on("message",e=>{try{const s=function(e){if(e.length<4)throw new Error("Invalid response: too short");const s=e[0],t=e[1],n=e[2],r=s>>4&15,o=4*(15&s),a=t>>4&15,c=15&t,i=n>>4&15,d=15&n;if(1!==r)throw new Error(`Unsupported protocol version: ${r}`);let u,g=o;!(1&~c)&&e.length>=g+4&&(u=e.readUInt32BE(g),g+=4);const y=!(2&~c);if(a===f){const s=e.readUInt32BE(g);g+=4;const t=e.readUInt32BE(g);return g+=4,{type:"error",sequence:u,isLast:!0,data:{code:s,message:e.slice(g,g+t).toString("utf-8")}}}if(a===h){const s=e.readUInt32BE(g);if(g+=4,0===s)return{type:"result",sequence:u,isLast:y,data:{}};let t,n=e.slice(g,g+s);if(d===$)try{n=l.gunzipSync(n)}catch(e){throw e}if(i===m){const e=n.toString("utf-8");try{t=JSON.parse(e)}catch(e){throw e}}else t={};return{type:"result",sequence:u,isLast:y,data:t}}throw new Error(`Unknown message type: ${a}`)}(e);if("error"===s.type){const e=s.data;this.callbacks.onError?.(new Error(`ASR Error ${e.code}: ${e.message}`))}else{const e=s.data;this.callbacks.onResult?.(e,s.isLast),s.isLast}}catch(e){this.callbacks.onError?.(e instanceof Error?e:new Error(String(e)))}}),this.ws.on("error",e=>{this.callbacks.onError?.(e),n(e)}),this.ws.on("close",()=>{this.isConnected=!1,this.ws=null,this.callbacks.onClose?.()})})}sendFullClientRequest(){if(!this.ws||this.ws.readyState!==E.OPEN)return;const e=function(e,s=!0){const t=b(d,g,m,s?$:w),n=JSON.stringify(e),r=Buffer.from(n,"utf-8"),o=s?l.gzipSync(r):r,a=Buffer.alloc(4);return a.writeUInt32BE(o.length,0),Buffer.concat([Buffer.from(t),a,o])}({user:{uid:"ai-chat-user"},audio:{format:this.sessionConfig.format||"pcm",rate:this.sessionConfig.sampleRate||16e3,bits:16,channel:1},request:{model_name:"bigmodel",enable_itn:this.sessionConfig.enableItn??!0,enable_punc:this.sessionConfig.enablePunc??!0,enable_ddc:this.sessionConfig.enableDdc??!1,show_utterances:this.sessionConfig.showUtterances??!0,result_type:"full"}});this.ws.send(e)}sendAudio(e){if(!this.ws||this.ws.readyState!==E.OPEN)return;const s=S(e,!1);this.ws.send(s)}finish(){if(!this.ws||this.ws.readyState!==E.OPEN)return;const e=S(Buffer.alloc(0),!0);this.ws.send(e)}disconnect(){this.ws&&(this.ws.close(),this.ws=null),this.isConnected=!1}get connected(){return this.isConnected&&this.ws?.readyState===E.OPEN}};import{ipcMain as A}from"electron";function D(e){const{channelPrefix:s="ai-chat",appId:t,accessKey:n,resourceId:r}=e,o=new Map;function a(e,s){let a=o.get(e);if(!a){a={client:new I({appId:t,accessKey:n,resourceId:r,useAsyncMode:!0}),webContents:s},o.set(e,a),s.on("destroyed",()=>{const s=o.get(e);s&&(s.client.disconnect(),o.delete(e))})}return a}return A.handle(`${s}:asr:start`,async(e,t)=>{const n=e.sender,r=a(n.id,n);r.client.connected&&r.client.disconnect();try{return await r.client.connect({onConnected:()=>{n.isDestroyed()||n.send(`${s}:asr:connected`)},onResult:(e,t)=>{n.isDestroyed()||n.send(`${s}:asr:result`,{result:e,isLast:t})},onError:e=>{n.isDestroyed()||n.send(`${s}:asr:error`,{message:e.message})},onClose:()=>{n.isDestroyed()||n.send(`${s}:asr:closed`)}},t),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),A.handle(`${s}:asr:sendAudio`,async(e,s)=>{const t=e.sender.id,n=o.get(t);if(!n||!n.client.connected)return{success:!1,error:"ASR 会话未启动"};try{const e=s instanceof ArrayBuffer?Buffer.from(s):Buffer.from(new Uint8Array(s));return n.client.sendAudio(e),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),A.handle(`${s}:asr:finish`,async e=>{const s=e.sender.id,t=o.get(s);if(!t||!t.client.connected)return{success:!1,error:"ASR 会话未启动"};try{return t.client.finish(),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),A.handle(`${s}:asr:stop`,async e=>{const s=e.sender.id,t=o.get(s);return t&&t.client.disconnect(),{success:!0}}),A.handle(`${s}:asr:status`,async e=>{const s=e.sender.id,t=o.get(s);return{connected:t?.client.connected??!1}}),A.handle(`${s}:asr:warmup`,async(e,s)=>{const t=e.sender,n=a(t.id,t);if(n.client.connected)return{success:!0};try{return await n.client.connect({onConnected:()=>{},onResult:()=>{},onError:()=>{},onClose:()=>{}},s),n.client.disconnect(),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),{cleanup:()=>{for(const e of o.values())e.client.disconnect();o.clear()}}}async function v(l){const{channelPrefix:d="ai-chat",dataDir:u,defaultContext:h={},...f}=l,g=n.join(u,"db.sqlite"),y=new Map,p=await i({type:"sqlite",sqlitePath:g}),m=()=>h,w=new r({...f,tools:l.tools,onToolApprovalRequest:async e=>{const s=global.currentWebContents;return!s||new Promise((t,n)=>{y.set(e.id,{resolve:t,reject:n,webContents:s}),s.send(`${d}:toolApprovalRequest`,{id:e.id,name:e.name,args:e.args})})},getAutoRunConfig:async()=>{try{const e=await p.getUserSetting("autoRunConfig",m());if(e)return JSON.parse(e)}catch(e){}}});e.handle(`${d}:models`,()=>o),e.handle(`${d}:getAllTools`,async()=>{0===w.tools.size&&w.toolConfig?await w.asyncInit():w.toolConfig;return w.getAllTools()}),e.handle(`${d}:getToolDefinitions`,async()=>{0===w.tools.size&&w.toolConfig&&await w.asyncInit();return Array.from(w.tools.values()).map(e=>({name:e.name,description:e.description,parameters:{type:"object",properties:e.parameters?.properties||{},required:e.parameters?.required||[]}}))}),e.handle(`${d}:executeTool`,async(e,s)=>{const{name:t,args:n}=s;0===w.tools.size&&w.toolConfig&&await w.asyncInit();try{const e=await w.executeTool(t,n),s="string"==typeof e?e:e&&"object"==typeof e&&"result"in e?e.result:JSON.stringify(e),r=w.tools.get(t),o=r?.resultType;return{success:!0,result:s,resultType:o}}catch(e){const s={success:!1,result:"",error:e instanceof Error?e.message:String(e)},t=c(e)?e.toolError:void 0;return t?{...s,toolError:t}:s}}),e.handle(`${d}:send`,async(e,s)=>{const t=e.sender,{message:n,images:r,sessionId:o}=s;let a=s.options||{};l.beforeChat&&(a=await l.beforeChat(a)||a),global.currentWebContents=t;try{for await(const e of w.chat(n,a,r))t.isDestroyed()||t.send(`${d}:progress`,{...e,sessionId:o})}catch(e){if(Error,!t.isDestroyed()){const s=e instanceof Error?{category:"api",message:e.message||String(e),cause:e.stack}:{category:"api",message:String(e)};t.send(`${d}:progress`,{type:"error",data:s,sessionId:o})}}finally{delete global.currentWebContents}}),e.handle(`${d}:toolApprovalResponse`,(e,s)=>{const{id:t,approved:n}=s,r=y.get(t);r&&(y.delete(t),r.resolve(n))}),e.handle(`${d}:cancel`,()=>{w.abort()}),e.handle(`${d}:settings:get`,async(e,s)=>p.getUserSetting(s,m())),e.handle(`${d}:settings:set`,async(e,s,t)=>(await p.setUserSetting(s,t,m()),{success:!0})),e.handle(`${d}:settings:getAll`,async()=>p.getUserSettings(m())),e.handle(`${d}:settings:delete`,async(e,s)=>(await p.deleteUserSetting(s,m()),{success:!0})),e.handle(`${d}:setCwd`,(e,s)=>{w.setCwd(s)}),e.handle(`${d}:config`,()=>w.getConfig()),e.handle(`${d}:sessions:list`,async()=>p.getSessions(m())),e.handle(`${d}:sessions:get`,async(e,s)=>p.getSession(s,m())),e.handle(`${d}:sessions:create`,async(e,s)=>{const t={id:s.id||crypto.randomUUID(),title:s.title||"新对话",model:s.model||a,mode:s.mode||"agent",webSearchEnabled:s.webSearchEnabled??!0,thinkingEnabled:s.thinkingEnabled??!0,hidden:s.hidden??!1};return p.createSession(t,m())}),e.handle(`${d}:sessions:update`,async(e,s,t)=>(await p.updateSession(s,t,m()),p.getSession(s,m()))),e.handle(`${d}:sessions:delete`,async(e,s)=>(await p.deleteSession(s,m()),{success:!0})),e.handle(`${d}:messages:list`,async(e,s)=>p.getMessages(s,m())),e.handle(`${d}:messages:save`,async(e,s)=>{const t=s.id||crypto.randomUUID(),n={id:t,clientId:t,sessionId:s.sessionId,role:s.role,content:s.content,images:s.images||[],model:s.model||null,mode:s.mode||null,webSearchEnabled:s.webSearchEnabled??null,thinkingEnabled:s.thinkingEnabled??null,steps:s.steps||null,operationIds:s.operationIds||null};return p.saveMessage(n,m())}),e.handle(`${d}:messages:update`,async(e,s)=>(await p.updateMessage(s.id,{content:s.content,steps:s.steps,usage:s.usage,duration:s.duration},m()),{success:!0})),e.handle(`${d}:messages:deleteAfter`,async(e,s,t)=>(await p.deleteMessagesAfter(s,new Date(t),m()),{success:!0})),e.handle(`${d}:messages:deleteAfterMessageId`,async(e,s,t)=>(await p.deleteMessagesAfterMessageId(s,t,m()),{success:!0})),e.handle(`${d}:operations:list`,async(e,s)=>p.getOperations(s,m())),e.handle(`${d}:trash:list`,async()=>p.getTrashItems?.(m())||[]),e.handle(`${d}:trash:restore`,async(e,s)=>p.restoreFromTrash?.(s,m())),e.handle(`${d}:openExternal`,async(e,t)=>s.openExternal(t)),e.handle(`${d}:fs:listDir`,async(e,s)=>{try{const e=t.readdirSync(s,{withFileTypes:!0}),r=[];for(const o of e){if(o.name.startsWith("."))continue;const e=n.join(s,o.name);try{const s=t.statSync(e);r.push({name:o.name,path:e,isDirectory:o.isDirectory(),size:s.size,modifiedAt:s.mtime,extension:o.isDirectory()?"":n.extname(o.name).toLowerCase()})}catch{}}return r.sort((e,s)=>e.isDirectory&&!s.isDirectory?-1:!e.isDirectory&&s.isDirectory?1:e.name.localeCompare(s.name))}catch(e){return[]}}),e.handle(`${d}:fs:exists`,async(e,s)=>t.existsSync(s)),e.handle(`${d}:fs:stat`,async(e,s)=>{try{const e=t.statSync(s);return{name:n.basename(s),path:s,isDirectory:e.isDirectory(),size:e.size,modifiedAt:e.mtime,extension:e.isDirectory()?"":n.extname(s).toLowerCase()}}catch{return null}}),e.handle(`${d}:fs:readFile`,async(e,s)=>{try{return t.readFileSync(s,"utf-8")}catch{return null}}),e.handle(`${d}:fs:readFileBase64`,async(e,s)=>{try{return t.readFileSync(s).toString("base64")}catch{return null}}),e.handle(`${d}:fs:homeDir`,async()=>process.env.HOME||process.env.USERPROFILE||"/"),e.handle(`${d}:fs:resolvePath`,async(e,s)=>{if(s.startsWith("~")){const e=process.env.HOME||process.env.USERPROFILE||"/";return n.join(e,s.slice(1))}return n.resolve(s)}),e.handle(`${d}:fs:parentDir`,async(e,s)=>n.dirname(s));const $=new Map;return e.handle(`${d}:fs:watchDir`,async(e,s)=>{const n=e.sender;$.has(s)&&($.get(s)?.close(),$.delete(s));try{const e=t.watch(s,{persistent:!1},(e,t)=>{n.isDestroyed()||n.send(`${d}:fs:dirChange`,{dirPath:s,eventType:e,filename:t})});return e.on("error",e=>{$.delete(s)}),$.set(s,e),!0}catch(e){return!1}}),e.handle(`${d}:fs:unwatchDir`,async(e,s)=>{const t=$.get(s);t&&(t.close(),$.delete(s))}),{agent:w,storage:p}}export{o as MODELS,D as createAsrBridge,v as createElectronBridge};
|
|
1
|
+
import{ipcMain as e,shell as s}from"electron";import*as t from"fs";import*as n from"path";import{HybridAgent as r,MODELS as o,DEFAULT_MODEL as a,isThrowableToolError as c}from"@huyooo/ai-chat-core";import{createStorage as i}from"@huyooo/ai-chat-storage";import*as l from"zlib";var d=1,u=2,h=9,f=15,g=0,y=2,p=0,m=1,w=0,$=1;function b(e,s,t,n){return[17,e<<4|s,t<<4|n,0]}function S(e,s=!1,t=!0){const n=b(u,s?y:g,p,t?$:w),r=t?l.gzipSync(e):e,o=Buffer.alloc(4);return o.writeUInt32BE(r.length,0),Buffer.concat([Buffer.from(n),o,r])}import E from"ws";import{v4 as C}from"uuid";var I=class{config;ws=null;callbacks={};connectId="";isConnected=!1;sessionConfig={};constructor(e){this.config=e}getWsUrl(){return!1!==this.config.useAsyncMode?"wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async":"wss://openspeech.bytedance.com/api/v3/sauc/bigmodel"}getResourceId(){return this.config.resourceId||"volc.bigasr.sauc.duration"}connect(e,s={}){return new Promise((t,n)=>{this.callbacks=e,this.sessionConfig=s,this.connectId=C();const r=this.getWsUrl();this.ws=new E(r,{headers:{"X-Api-App-Key":this.config.appId,"X-Api-Access-Key":this.config.accessKey,"X-Api-Resource-Id":this.getResourceId(),"X-Api-Connect-Id":this.connectId}}),this.ws.on("open",()=>{this.isConnected=!0,this.sendFullClientRequest(),this.callbacks.onConnected?.(),t()}),this.ws.on("message",e=>{try{const s=function(e){if(e.length<4)throw new Error("Invalid response: too short");const s=e[0],t=e[1],n=e[2],r=s>>4&15,o=4*(15&s),a=t>>4&15,c=15&t,i=n>>4&15,d=15&n;if(1!==r)throw new Error(`Unsupported protocol version: ${r}`);let u,g=o;!(1&~c)&&e.length>=g+4&&(u=e.readUInt32BE(g),g+=4);const y=!(2&~c);if(a===f){const s=e.readUInt32BE(g);g+=4;const t=e.readUInt32BE(g);return g+=4,{type:"error",sequence:u,isLast:!0,data:{code:s,message:e.slice(g,g+t).toString("utf-8")}}}if(a===h){const s=e.readUInt32BE(g);if(g+=4,0===s)return{type:"result",sequence:u,isLast:y,data:{}};let t,n=e.slice(g,g+s);if(d===$)try{n=l.gunzipSync(n)}catch(e){throw e}if(i===m){const e=n.toString("utf-8");try{t=JSON.parse(e)}catch(e){throw e}}else t={};return{type:"result",sequence:u,isLast:y,data:t}}throw new Error(`Unknown message type: ${a}`)}(e);if("error"===s.type){const e=s.data;this.callbacks.onError?.(new Error(`ASR Error ${e.code}: ${e.message}`))}else{const e=s.data;this.callbacks.onResult?.(e,s.isLast),s.isLast}}catch(e){this.callbacks.onError?.(e instanceof Error?e:new Error(String(e)))}}),this.ws.on("error",e=>{this.callbacks.onError?.(e),n(e)}),this.ws.on("close",()=>{this.isConnected=!1,this.ws=null,this.callbacks.onClose?.()})})}sendFullClientRequest(){if(!this.ws||this.ws.readyState!==E.OPEN)return;const e=function(e,s=!0){const t=b(d,g,m,s?$:w),n=JSON.stringify(e),r=Buffer.from(n,"utf-8"),o=s?l.gzipSync(r):r,a=Buffer.alloc(4);return a.writeUInt32BE(o.length,0),Buffer.concat([Buffer.from(t),a,o])}({user:{uid:"ai-chat-user"},audio:{format:this.sessionConfig.format||"pcm",rate:this.sessionConfig.sampleRate||16e3,bits:16,channel:1},request:{model_name:"bigmodel",enable_itn:this.sessionConfig.enableItn??!0,enable_punc:this.sessionConfig.enablePunc??!0,enable_ddc:this.sessionConfig.enableDdc??!1,show_utterances:this.sessionConfig.showUtterances??!0,result_type:"full"}});this.ws.send(e)}sendAudio(e){if(!this.ws||this.ws.readyState!==E.OPEN)return;const s=S(e,!1);this.ws.send(s)}finish(){if(!this.ws||this.ws.readyState!==E.OPEN)return;const e=S(Buffer.alloc(0),!0);this.ws.send(e)}disconnect(){this.ws&&(this.ws.close(),this.ws=null),this.isConnected=!1}get connected(){return this.isConnected&&this.ws?.readyState===E.OPEN}};import{ipcMain as A}from"electron";function D(e){const{channelPrefix:s="ai-chat",appId:t,accessKey:n,resourceId:r}=e,o=new Map;function a(e,s){let a=o.get(e);if(!a){a={client:new I({appId:t,accessKey:n,resourceId:r,useAsyncMode:!0}),webContents:s},o.set(e,a),s.on("destroyed",()=>{const s=o.get(e);s&&(s.client.disconnect(),o.delete(e))})}return a}return A.handle(`${s}:asr:start`,async(e,t)=>{const n=e.sender,r=a(n.id,n);r.client.connected&&r.client.disconnect();try{return await r.client.connect({onConnected:()=>{n.isDestroyed()||n.send(`${s}:asr:connected`)},onResult:(e,t)=>{n.isDestroyed()||n.send(`${s}:asr:result`,{result:e,isLast:t})},onError:e=>{n.isDestroyed()||n.send(`${s}:asr:error`,{message:e.message})},onClose:()=>{n.isDestroyed()||n.send(`${s}:asr:closed`)}},t),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),A.handle(`${s}:asr:sendAudio`,async(e,s)=>{const t=e.sender.id,n=o.get(t);if(!n||!n.client.connected)return{success:!1,error:"ASR 会话未启动"};try{const e=s instanceof ArrayBuffer?Buffer.from(s):Buffer.from(new Uint8Array(s));return n.client.sendAudio(e),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),A.handle(`${s}:asr:finish`,async e=>{const s=e.sender.id,t=o.get(s);if(!t||!t.client.connected)return{success:!1,error:"ASR 会话未启动"};try{return t.client.finish(),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),A.handle(`${s}:asr:stop`,async e=>{const s=e.sender.id,t=o.get(s);return t&&t.client.disconnect(),{success:!0}}),A.handle(`${s}:asr:status`,async e=>{const s=e.sender.id,t=o.get(s);return{connected:t?.client.connected??!1}}),A.handle(`${s}:asr:warmup`,async(e,s)=>{const t=e.sender,n=a(t.id,t);if(n.client.connected)return{success:!0};try{return await n.client.connect({onConnected:()=>{},onResult:()=>{},onError:()=>{},onClose:()=>{}},s),n.client.disconnect(),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}),{cleanup:()=>{for(const e of o.values())e.client.disconnect();o.clear()}}}async function v(l){const{channelPrefix:d="ai-chat",dataDir:u,defaultContext:h={},...f}=l,g=n.join(u,"db.sqlite"),y=new Map,p=await i({type:"sqlite",sqlitePath:g}),m=()=>h,w=new r({...f,tools:l.tools,onToolApprovalRequest:async e=>{const s=global.currentWebContents;return!s||new Promise((t,n)=>{y.set(e.id,{resolve:t,reject:n,webContents:s}),s.send(`${d}:toolApprovalRequest`,{id:e.id,name:e.name,args:e.args})})},getAutoRunConfig:async()=>{try{const e=await p.getUserSetting("autoRunConfig",m());if(e)return JSON.parse(e)}catch(e){}}});e.handle(`${d}:models`,()=>o),e.handle(`${d}:getAllTools`,async()=>{0===w.tools.size&&w.toolConfig?await w.asyncInit():w.toolConfig;return w.getAllTools()}),e.handle(`${d}:getToolDefinitions`,async()=>{0===w.tools.size&&w.toolConfig&&await w.asyncInit();return Array.from(w.tools.values()).map(e=>({name:e.name,description:e.description,parameters:{type:"object",properties:e.parameters?.properties||{},required:e.parameters?.required||[]}}))}),e.handle(`${d}:executeTool`,async(e,s)=>{const{name:t,args:n}=s;0===w.tools.size&&w.toolConfig&&await w.asyncInit();try{const e=await w.executeTool(t,n),s="string"==typeof e?e:e&&"object"==typeof e&&"result"in e?e.result:JSON.stringify(e),r=w.tools.get(t),o=r?.ui;return{success:!0,result:s,ui:o}}catch(e){const s={success:!1,result:"",error:e instanceof Error?e.message:String(e)},t=c(e)?e.toolError:void 0;return t?{...s,toolError:t}:s}}),e.handle(`${d}:send`,async(e,s)=>{const t=e.sender,{message:n,images:r,sessionId:o}=s;let a=s.options||{};l.beforeChat&&(a=await l.beforeChat(a)||a),global.currentWebContents=t;try{for await(const e of w.chat(n,a,r))t.isDestroyed()||t.send(`${d}:progress`,{...e,sessionId:o})}catch(e){if(Error,!t.isDestroyed()){const s=e instanceof Error?{category:"api",message:e.message||String(e),cause:e.stack}:{category:"api",message:String(e)};t.send(`${d}:progress`,{type:"error",data:s,sessionId:o})}}finally{delete global.currentWebContents}}),e.handle(`${d}:toolApprovalResponse`,(e,s)=>{const{id:t,approved:n}=s,r=y.get(t);r&&(y.delete(t),r.resolve(n))}),e.handle(`${d}:cancel`,()=>{w.abort()}),e.handle(`${d}:settings:get`,async(e,s)=>p.getUserSetting(s,m())),e.handle(`${d}:settings:set`,async(e,s,t)=>(await p.setUserSetting(s,t,m()),{success:!0})),e.handle(`${d}:settings:getAll`,async()=>p.getUserSettings(m())),e.handle(`${d}:settings:delete`,async(e,s)=>(await p.deleteUserSetting(s,m()),{success:!0})),e.handle(`${d}:setCwd`,(e,s)=>{w.setCwd(s)}),e.handle(`${d}:config`,()=>w.getConfig()),e.handle(`${d}:sessions:list`,async()=>p.getSessions(m())),e.handle(`${d}:sessions:get`,async(e,s)=>p.getSession(s,m())),e.handle(`${d}:sessions:create`,async(e,s)=>{const t={id:s.id||crypto.randomUUID(),title:s.title||"新对话",model:s.model||a,mode:s.mode||"agent",webSearchEnabled:s.webSearchEnabled??!0,thinkingEnabled:s.thinkingEnabled??!0,hidden:s.hidden??!1};return p.createSession(t,m())}),e.handle(`${d}:sessions:update`,async(e,s,t)=>(await p.updateSession(s,t,m()),p.getSession(s,m()))),e.handle(`${d}:sessions:delete`,async(e,s)=>(await p.deleteSession(s,m()),{success:!0})),e.handle(`${d}:messages:list`,async(e,s)=>p.getMessages(s,m())),e.handle(`${d}:messages:save`,async(e,s)=>{const t=s.id||crypto.randomUUID(),n={id:t,clientId:t,sessionId:s.sessionId,role:s.role,content:s.content,images:s.images||[],model:s.model||null,mode:s.mode||null,webSearchEnabled:s.webSearchEnabled??null,thinkingEnabled:s.thinkingEnabled??null,steps:s.steps||null,operationIds:s.operationIds||null};return p.saveMessage(n,m())}),e.handle(`${d}:messages:update`,async(e,s)=>(await p.updateMessage(s.id,{content:s.content,steps:s.steps,usage:s.usage,duration:s.duration},m()),{success:!0})),e.handle(`${d}:messages:deleteAfter`,async(e,s,t)=>(await p.deleteMessagesAfter(s,new Date(t),m()),{success:!0})),e.handle(`${d}:messages:deleteAfterMessageId`,async(e,s,t)=>(await p.deleteMessagesAfterMessageId(s,t,m()),{success:!0})),e.handle(`${d}:operations:list`,async(e,s)=>p.getOperations(s,m())),e.handle(`${d}:trash:list`,async()=>p.getTrashItems?.(m())||[]),e.handle(`${d}:trash:restore`,async(e,s)=>p.restoreFromTrash?.(s,m())),e.handle(`${d}:openExternal`,async(e,t)=>s.openExternal(t)),e.handle(`${d}:fs:listDir`,async(e,s)=>{try{const e=t.readdirSync(s,{withFileTypes:!0}),r=[];for(const o of e){if(o.name.startsWith("."))continue;const e=n.join(s,o.name);try{const s=t.statSync(e);r.push({name:o.name,path:e,isDirectory:o.isDirectory(),size:s.size,modifiedAt:s.mtime,extension:o.isDirectory()?"":n.extname(o.name).toLowerCase()})}catch{}}return r.sort((e,s)=>e.isDirectory&&!s.isDirectory?-1:!e.isDirectory&&s.isDirectory?1:e.name.localeCompare(s.name))}catch(e){return[]}}),e.handle(`${d}:fs:exists`,async(e,s)=>t.existsSync(s)),e.handle(`${d}:fs:stat`,async(e,s)=>{try{const e=t.statSync(s);return{name:n.basename(s),path:s,isDirectory:e.isDirectory(),size:e.size,modifiedAt:e.mtime,extension:e.isDirectory()?"":n.extname(s).toLowerCase()}}catch{return null}}),e.handle(`${d}:fs:readFile`,async(e,s)=>{try{return t.readFileSync(s,"utf-8")}catch{return null}}),e.handle(`${d}:fs:readFileBase64`,async(e,s)=>{try{return t.readFileSync(s).toString("base64")}catch{return null}}),e.handle(`${d}:fs:homeDir`,async()=>process.env.HOME||process.env.USERPROFILE||"/"),e.handle(`${d}:fs:resolvePath`,async(e,s)=>{if(s.startsWith("~")){const e=process.env.HOME||process.env.USERPROFILE||"/";return n.join(e,s.slice(1))}return n.resolve(s)}),e.handle(`${d}:fs:parentDir`,async(e,s)=>n.dirname(s));const $=new Map;return e.handle(`${d}:fs:watchDir`,async(e,s)=>{const n=e.sender;$.has(s)&&($.get(s)?.close(),$.delete(s));try{const e=t.watch(s,{persistent:!1},(e,t)=>{n.isDestroyed()||n.send(`${d}:fs:dirChange`,{dirPath:s,eventType:e,filename:t})});return e.on("error",e=>{$.delete(s)}),$.set(s,e),!0}catch(e){return!1}}),e.handle(`${d}:fs:unwatchDir`,async(e,s)=>{const t=$.get(s);t&&(t.close(),$.delete(s))}),{agent:w,storage:p}}export{o as MODELS,D as createAsrBridge,v as createElectronBridge};
|
package/dist/preload/index.d.ts
CHANGED
|
@@ -24,7 +24,11 @@ interface ToolExecutionResult {
|
|
|
24
24
|
success: boolean;
|
|
25
25
|
result: string;
|
|
26
26
|
error?: string;
|
|
27
|
-
|
|
27
|
+
ui?: {
|
|
28
|
+
type: 'render' | 'action';
|
|
29
|
+
name: string;
|
|
30
|
+
props?: Record<string, unknown>;
|
|
31
|
+
};
|
|
28
32
|
toolError?: _huyooo_ai_chat_core_events.ToolErrorShape;
|
|
29
33
|
}
|
|
30
34
|
/** Electron Bridge 接口(完整的 IPC 桥接) */
|
package/dist/renderer/index.d.ts
CHANGED
|
@@ -24,7 +24,11 @@ interface ToolExecutionResult {
|
|
|
24
24
|
success: boolean;
|
|
25
25
|
result: string;
|
|
26
26
|
error?: string;
|
|
27
|
-
|
|
27
|
+
ui?: {
|
|
28
|
+
type: 'render' | 'action';
|
|
29
|
+
name: string;
|
|
30
|
+
props?: Record<string, unknown>;
|
|
31
|
+
};
|
|
28
32
|
toolError?: _huyooo_ai_chat_core_events.ToolErrorShape;
|
|
29
33
|
}
|
|
30
34
|
/** Electron Bridge 接口(完整的 IPC 桥接) */
|
package/dist/renderer/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(){try{return"undefined"!=typeof localStorage&&"true"===localStorage.getItem("AI_CHAT_DEBUG")}catch{return!1}}function s(s){return{debug:(...s)=>{e()},info:(...s)=>{e()},warn:(...e)=>{},error:(...e)=>{}}}export*from"@huyooo/ai-chat-types";var t=s();function n(e={}){const{bridgeName:s="aiChatBridge"}=e,t=()=>{const e=window[s];if(!e)throw new Error("AI Chat Bridge not found. Make sure to call exposeElectronBridge() in preload.");return e};return{getModels:async()=>t().getModels(),async getAllTools(){const e=t();return"function"==typeof e.getAllTools?e.getAllTools():[]},async*sendMessage(e,s,n,r){const a=t(),o=[];let c=null,i=!1;const l=a.onProgress(e=>{const s=e;r&&s.sessionId&&s.sessionId!==r||(o.push(e),c?.(),"done"!==e.type&&"error"!==e.type||(i=!0))});a.send({message:e,images:n,options:s,sessionId:r});try{for(;!i||o.length>0;){for(;0===o.length&&!i;)await new Promise(e=>c=e);if(o.length>0){const e=o.shift();if(yield e,"done"===e.type||"error"===e.type)break}}}finally{l()}},cancel(){t().cancel()},setCwd(e){t().setCwd(e)},getSessions:async()=>t().getSessions(),getSession:async e=>t().getSession(e),createSession:async e=>t().createSession(e),updateSession:async(e,s)=>t().updateSession(e,s),async deleteSession(e){await t().deleteSession(e)},getMessages:async e=>t().getMessages(e),saveMessage:async e=>t().saveMessage(e),async updateMessage(e){await t().updateMessage(e)},async deleteMessagesAfter(e,s){await t().deleteMessagesAfter(e,s)},async deleteMessagesAfterMessageId(e,s){await t().deleteMessagesAfterMessageId(e,s)},getOperations:async e=>t().getOperations(e),getTrashItems:async()=>t().getTrashItems(),restoreFromTrash:async e=>t().restoreFromTrash(e),listDir:async e=>t().listDir(e),exists:async e=>t().exists(e),stat:async e=>t().stat(e),readFile:async e=>t().readFile(e),readFileBase64:async e=>t().readFileBase64(e),homeDir:async()=>t().homeDir(),resolvePath:async e=>t().resolvePath(e),parentDir:async e=>t().parentDir(e),watchDir:async e=>t().watchDir(e),unwatchDir:async e=>t().unwatchDir(e),onDirChange:e=>t().onDirChange(e),async getSetting(e){const s=t();return s.getSetting?s.getSetting(e):null},async setSetting(e,s){const n=t();n.setSetting&&await n.setSetting(e,s)},async getAllSettings(){const e=t();return e.getAllSettings?e.getAllSettings():{}},async deleteSetting(e){const s=t();s.deleteSetting&&await s.deleteSetting(e)},async getIndexStats(){const e=t();return e.getIndexStats?e.getIndexStats():{totalDocuments:0,indexSize:0,lastUpdated:null}},async getIndexStatus(){const e=t();return e.getIndexStatus?e.getIndexStatus():{isIndexing:!1,lastProgress:null}},async syncIndex(){const e=t();return e.syncIndex?e.syncIndex():{success:!1}},async cancelIndex(){const e=t();return e.cancelIndex?e.cancelIndex():{success:!1}},async deleteIndex(){const e=t();return e.deleteIndex?e.deleteIndex():{success:!1}},async registerIndexListener(){const e=t();return e.registerIndexListener?e.registerIndexListener():{success:!1}},async unregisterIndexListener(){const e=t();return e.unregisterIndexListener?e.unregisterIndexListener():{success:!1}},onIndexProgress(e){const s=t();return s.onIndexProgress?s.onIndexProgress(e):()=>{}},onToolApprovalRequest(e){const s=t();return s.onToolApprovalRequest?s.onToolApprovalRequest(e):()=>{}},async respondToolApproval(e,s){const n=t();if(n.respondToolApproval)return n.respondToolApproval(e,s)},async asrStart(e){const s=t();return s.asrStart?s.asrStart(e):{success:!1,error:"ASR not supported"}},async asrSendAudio(e){const s=t();return s.asrSendAudio?s.asrSendAudio(e):{success:!1,error:"ASR not supported"}},async asrFinish(){const e=t();return e.asrFinish?e.asrFinish():{success:!1,error:"ASR not supported"}},async asrStop(){const e=t();return e.asrStop?e.asrStop():{success:!0}},async asrStatus(){const e=t();return e.asrStatus?e.asrStatus():{connected:!1}},async asrWarmup(e){const s=t();return s.asrWarmup?s.asrWarmup(e):{success:!1,error:"ASR not supported"}},onAsrConnected(e){const s=t();return s.onAsrConnected?s.onAsrConnected(e):()=>{}},onAsrResult(e){const s=t();return s.onAsrResult?s.onAsrResult(e):()=>{}},onAsrError(e){const s=t();return s.onAsrError?s.onAsrError(e):()=>{}},onAsrClosed(e){const s=t();return s.onAsrClosed?s.onAsrClosed(e):()=>{}},async openExternal(e){const s=t();if(s.openExternal)return s.openExternal(e)}}}function r(e){const{bridgeName:s="aiChatBridge",remote:n}=e,{baseURL:r,getToken:a,getAppId:o}=n,c=()=>{const e=window[s];if(!e)throw new Error("AI Chat Bridge not found. Make sure to call exposeElectronBridge() in preload.");return e};async function i(){const e=await a(),s=o?await o():null,t={};return e&&(t.Authorization=`Bearer ${e}`),s&&(t["app-id"]=s),t}function l(e){try{return JSON.parse(e)}catch{return null}}let d=null;return{getModels:async()=>(await async function(e,s={}){const t=await i(),n=s.method?.toUpperCase()||"GET";["POST","PUT","PATCH"].includes(n)&&(t["Content-Type"]="application/json");const a=await fetch(`${r}${e}`,{...s,headers:{...t,...s.headers||{}}});if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);return a.json()}("/chat/models")).models||[],async getAllTools(){const e=c();return"function"==typeof e.getAllTools?e.getAllTools():[]},async*sendMessage(e,s,n,a){d&&d.abort(),d=new AbortController;const{signal:o}=d;try{const d=c(),u="function"==typeof d.getToolDefinitions?await d.getToolDefinitions():[];let g=e,y=s,p=n;for(let e=0;e<10;e++){const e=await i(),s=await fetch(`${r}/chat/stream`,{method:"POST",headers:{...e,"Content-Type":"application/json",Accept:"text/event-stream"},body:JSON.stringify({message:g,options:y,images:p,sessionId:a,tools:u}),signal:o});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);const n=s.body?.getReader();if(!n)throw new Error("Response body is not readable");const c=new TextDecoder;let S="",A=[],x="",h=!1;for(;;){const{done:e,value:s}=await n.read();if(e)break;S+=c.decode(s,{stream:!0});const r=S.split("\n");S=r.pop()||"";for(const e of r)if(e.startsWith("data: ")){const s=e.slice(6).trim();if("[DONE]"===s)break;const n=l(s);if(n)if("text_delta"===n.type&&(x+=n.data.content||""),"tool_call_request"===n.type){const{id:e,name:s,args:r}=n.data;t.debug("收到 tool_call_request:",s,"args:",JSON.stringify(r).slice(0,500)),A.push({id:e,name:s,args:r}),yield{type:"tool_call_start",data:{id:e,name:s,args:r,startedAt:Date.now()}}}else if("done"===n.type)A.length>0?h=!0:yield n;else if(yield n,"error"===n.type)return}}if(S.startsWith("data: ")){const e=S.slice(6).trim();if(e&&"[DONE]"!==e){const s=l(e);s&&"tool_call_request"!==s.type&&("done"===s.type&&A.length>0?h=!0:yield s)}}if(!(A.length>0&&h))break;{t.debug("执行工具:",A.map(e=>e.name).join(", "));const e=[];for(const s of A){const n=Date.now();t.debug(`executeTool(${s.name}) args:`,JSON.stringify(s.args).slice(0,500));const r=await d.executeTool(s.name,s.args);t.debug(`executeTool(${s.name}) result:`,JSON.stringify(r).slice(0,500)),yield{type:"tool_call_result",data:{id:s.id,name:s.name,result:r.result,success:r.success,error:r.error,toolError:r.toolError,resultType:r.resultType,endedAt:Date.now(),duration:Date.now()-n}},e.push({role:"tool",content:r.result,tool_call_id:s.id})}const s=A.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:JSON.stringify(e.args)}})),n=[...y?.history||[],...g?[{role:"user",content:g}]:[],{role:"assistant",content:x,tool_calls:s},...e];t.debug("继续对话,新 history 长度:",n.length),g="",y={...y,history:n},p=void 0,x=""}}}finally{d=null}},cancel(){d&&(d.abort(),d=null)},setCwd(e){c().setCwd(e)},getSessions:async()=>c().getSessions(),getSession:async e=>c().getSession(e),createSession:async e=>c().createSession(e),updateSession:async(e,s)=>c().updateSession(e,s),async deleteSession(e){await c().deleteSession(e)},getMessages:async e=>c().getMessages(e),saveMessage:async e=>c().saveMessage(e),async updateMessage(e){await c().updateMessage(e)},async deleteMessagesAfter(e,s){await c().deleteMessagesAfter(e,s)},async deleteMessagesAfterMessageId(e,s){await c().deleteMessagesAfterMessageId(e,s)},getOperations:async e=>c().getOperations(e),getTrashItems:async()=>c().getTrashItems(),restoreFromTrash:async e=>c().restoreFromTrash(e),listDir:async e=>c().listDir(e),exists:async e=>c().exists(e),stat:async e=>c().stat(e),readFile:async e=>c().readFile(e),readFileBase64:async e=>c().readFileBase64(e),homeDir:async()=>c().homeDir(),resolvePath:async e=>c().resolvePath(e),parentDir:async e=>c().parentDir(e),watchDir:async e=>c().watchDir(e),unwatchDir:async e=>c().unwatchDir(e),onDirChange:e=>c().onDirChange(e),async getSetting(e){const s=c();return s.getSetting?s.getSetting(e):null},async setSetting(e,s){const t=c();t.setSetting&&await t.setSetting(e,s)},async getAllSettings(){const e=c();return e.getAllSettings?e.getAllSettings():{}},async deleteSetting(e){const s=c();s.deleteSetting&&await s.deleteSetting(e)},async getIndexStats(){const e=c();return e.getIndexStats?e.getIndexStats():{totalDocuments:0,indexSize:0,lastUpdated:null}},async getIndexStatus(){const e=c();return e.getIndexStatus?e.getIndexStatus():{isIndexing:!1,lastProgress:null}},async syncIndex(){const e=c();return e.syncIndex?e.syncIndex():{success:!1}},async cancelIndex(){const e=c();return e.cancelIndex?e.cancelIndex():{success:!1}},async deleteIndex(){const e=c();return e.deleteIndex?e.deleteIndex():{success:!1}},async registerIndexListener(){const e=c();return e.registerIndexListener?e.registerIndexListener():{success:!1}},async unregisterIndexListener(){const e=c();return e.unregisterIndexListener?e.unregisterIndexListener():{success:!1}},onIndexProgress(e){const s=c();return s.onIndexProgress?s.onIndexProgress(e):()=>{}},onToolApprovalRequest:e=>()=>{},async respondToolApproval(e,s){},async asrStart(e){const s=c();return s.asrStart?s.asrStart(e):{success:!1,error:"ASR not supported"}},async asrSendAudio(e){const s=c();return s.asrSendAudio?s.asrSendAudio(e):{success:!1,error:"ASR not supported"}},async asrFinish(){const e=c();return e.asrFinish?e.asrFinish():{success:!1,error:"ASR not supported"}},async asrStop(){const e=c();return e.asrStop?e.asrStop():{success:!0}},async asrStatus(){const e=c();return e.asrStatus?e.asrStatus():{connected:!1}},async asrWarmup(e){const s=c();return s.asrWarmup?s.asrWarmup(e):{success:!1,error:"ASR not supported"}},onAsrConnected(e){const s=c();return s.onAsrConnected?s.onAsrConnected(e):()=>{}},onAsrResult(e){const s=c();return s.onAsrResult?s.onAsrResult(e):()=>{}},onAsrError(e){const s=c();return s.onAsrError?s.onAsrError(e):()=>{}},onAsrClosed(e){const s=c();return s.onAsrClosed?s.onAsrClosed(e):()=>{}},async openExternal(e){const s=c();if(s.openExternal)return s.openExternal(e)}}}export{n as createElectronAdapter,r as createHybridAdapter,s as createLogger};
|
|
1
|
+
function e(){try{return"undefined"!=typeof localStorage&&"true"===localStorage.getItem("AI_CHAT_DEBUG")}catch{return!1}}function s(s){return{debug:(...s)=>{e()},info:(...s)=>{e()},warn:(...e)=>{},error:(...e)=>{}}}export*from"@huyooo/ai-chat-types";var t=s();function n(e={}){const{bridgeName:s="aiChatBridge"}=e,t=()=>{const e=window[s];if(!e)throw new Error("AI Chat Bridge not found. Make sure to call exposeElectronBridge() in preload.");return e};return{getModels:async()=>t().getModels(),async getAllTools(){const e=t();return"function"==typeof e.getAllTools?e.getAllTools():[]},async*sendMessage(e,s,n,r){const a=t(),o=[];let c=null,i=!1;const l=a.onProgress(e=>{const s=e;r&&s.sessionId&&s.sessionId!==r||(o.push(e),c?.(),"done"!==e.type&&"error"!==e.type||(i=!0))});a.send({message:e,images:n,options:s,sessionId:r});try{for(;!i||o.length>0;){for(;0===o.length&&!i;)await new Promise(e=>c=e);if(o.length>0){const e=o.shift();if(yield e,"done"===e.type||"error"===e.type)break}}}finally{l()}},cancel(){t().cancel()},setCwd(e){t().setCwd(e)},getSessions:async()=>t().getSessions(),getSession:async e=>t().getSession(e),createSession:async e=>t().createSession(e),updateSession:async(e,s)=>t().updateSession(e,s),async deleteSession(e){await t().deleteSession(e)},getMessages:async e=>t().getMessages(e),saveMessage:async e=>t().saveMessage(e),async updateMessage(e){await t().updateMessage(e)},async deleteMessagesAfter(e,s){await t().deleteMessagesAfter(e,s)},async deleteMessagesAfterMessageId(e,s){await t().deleteMessagesAfterMessageId(e,s)},getOperations:async e=>t().getOperations(e),getTrashItems:async()=>t().getTrashItems(),restoreFromTrash:async e=>t().restoreFromTrash(e),listDir:async e=>t().listDir(e),exists:async e=>t().exists(e),stat:async e=>t().stat(e),readFile:async e=>t().readFile(e),readFileBase64:async e=>t().readFileBase64(e),homeDir:async()=>t().homeDir(),resolvePath:async e=>t().resolvePath(e),parentDir:async e=>t().parentDir(e),watchDir:async e=>t().watchDir(e),unwatchDir:async e=>t().unwatchDir(e),onDirChange:e=>t().onDirChange(e),async getSetting(e){const s=t();return s.getSetting?s.getSetting(e):null},async setSetting(e,s){const n=t();n.setSetting&&await n.setSetting(e,s)},async getAllSettings(){const e=t();return e.getAllSettings?e.getAllSettings():{}},async deleteSetting(e){const s=t();s.deleteSetting&&await s.deleteSetting(e)},async getIndexStats(){const e=t();return e.getIndexStats?e.getIndexStats():{totalDocuments:0,indexSize:0,lastUpdated:null}},async getIndexStatus(){const e=t();return e.getIndexStatus?e.getIndexStatus():{isIndexing:!1,lastProgress:null}},async syncIndex(){const e=t();return e.syncIndex?e.syncIndex():{success:!1}},async cancelIndex(){const e=t();return e.cancelIndex?e.cancelIndex():{success:!1}},async deleteIndex(){const e=t();return e.deleteIndex?e.deleteIndex():{success:!1}},async registerIndexListener(){const e=t();return e.registerIndexListener?e.registerIndexListener():{success:!1}},async unregisterIndexListener(){const e=t();return e.unregisterIndexListener?e.unregisterIndexListener():{success:!1}},onIndexProgress(e){const s=t();return s.onIndexProgress?s.onIndexProgress(e):()=>{}},onToolApprovalRequest(e){const s=t();return s.onToolApprovalRequest?s.onToolApprovalRequest(e):()=>{}},async respondToolApproval(e,s){const n=t();if(n.respondToolApproval)return n.respondToolApproval(e,s)},async asrStart(e){const s=t();return s.asrStart?s.asrStart(e):{success:!1,error:"ASR not supported"}},async asrSendAudio(e){const s=t();return s.asrSendAudio?s.asrSendAudio(e):{success:!1,error:"ASR not supported"}},async asrFinish(){const e=t();return e.asrFinish?e.asrFinish():{success:!1,error:"ASR not supported"}},async asrStop(){const e=t();return e.asrStop?e.asrStop():{success:!0}},async asrStatus(){const e=t();return e.asrStatus?e.asrStatus():{connected:!1}},async asrWarmup(e){const s=t();return s.asrWarmup?s.asrWarmup(e):{success:!1,error:"ASR not supported"}},onAsrConnected(e){const s=t();return s.onAsrConnected?s.onAsrConnected(e):()=>{}},onAsrResult(e){const s=t();return s.onAsrResult?s.onAsrResult(e):()=>{}},onAsrError(e){const s=t();return s.onAsrError?s.onAsrError(e):()=>{}},onAsrClosed(e){const s=t();return s.onAsrClosed?s.onAsrClosed(e):()=>{}},async openExternal(e){const s=t();if(s.openExternal)return s.openExternal(e)}}}function r(e){const{bridgeName:s="aiChatBridge",remote:n}=e,{baseURL:r,getToken:a,getAppId:o}=n,c=()=>{const e=window[s];if(!e)throw new Error("AI Chat Bridge not found. Make sure to call exposeElectronBridge() in preload.");return e};async function i(){const e=await a(),s=o?await o():null,t={};return e&&(t.Authorization=`Bearer ${e}`),s&&(t["app-id"]=s),t}function l(e){try{return JSON.parse(e)}catch{return null}}let d=null;return{getModels:async()=>(await async function(e,s={}){const t=await i(),n=s.method?.toUpperCase()||"GET";["POST","PUT","PATCH"].includes(n)&&(t["Content-Type"]="application/json");const a=await fetch(`${r}${e}`,{...s,headers:{...t,...s.headers||{}}});if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);return a.json()}("/chat/models")).models||[],async getAllTools(){const e=c();return"function"==typeof e.getAllTools?e.getAllTools():[]},async*sendMessage(e,s,n,a){d&&d.abort(),d=new AbortController;const{signal:o}=d;try{const d=c(),u="function"==typeof d.getToolDefinitions?await d.getToolDefinitions():[];let g=e,y=s,p=n;for(let e=0;e<10;e++){const e=await i(),s=await fetch(`${r}/chat/stream`,{method:"POST",headers:{...e,"Content-Type":"application/json",Accept:"text/event-stream"},body:JSON.stringify({message:g,options:y,images:p,sessionId:a,tools:u}),signal:o});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);const n=s.body?.getReader();if(!n)throw new Error("Response body is not readable");const c=new TextDecoder;let S="",A=[],x="",h=!1;for(;;){const{done:e,value:s}=await n.read();if(e)break;S+=c.decode(s,{stream:!0});const r=S.split("\n");S=r.pop()||"";for(const e of r)if(e.startsWith("data: ")){const s=e.slice(6).trim();if("[DONE]"===s)break;const n=l(s);if(n)if("text_delta"===n.type&&(x+=n.data.content||""),"tool_call_request"===n.type){const{id:e,name:s,args:r}=n.data;t.debug("收到 tool_call_request:",s,"args:",JSON.stringify(r).slice(0,500)),A.push({id:e,name:s,args:r}),yield{type:"tool_call_start",data:{id:e,name:s,args:r,startedAt:Date.now()}}}else if("done"===n.type)A.length>0?h=!0:yield n;else if(yield n,"error"===n.type)return}}if(S.startsWith("data: ")){const e=S.slice(6).trim();if(e&&"[DONE]"!==e){const s=l(e);s&&"tool_call_request"!==s.type&&("done"===s.type&&A.length>0?h=!0:yield s)}}if(!(A.length>0&&h))break;{t.debug("执行工具:",A.map(e=>e.name).join(", "));const e=[];for(const s of A){const n=Date.now();t.debug(`executeTool(${s.name}) args:`,JSON.stringify(s.args).slice(0,500));const r=await d.executeTool(s.name,s.args);t.debug(`executeTool(${s.name}) result:`,JSON.stringify(r).slice(0,500)),yield{type:"tool_call_result",data:{id:s.id,name:s.name,result:r.result,success:r.success,error:r.error,toolError:r.toolError,ui:r.ui,endedAt:Date.now(),duration:Date.now()-n}},e.push({role:"tool",content:r.result,tool_call_id:s.id})}const s=A.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:JSON.stringify(e.args)}})),n=[...y?.history||[],...g?[{role:"user",content:g}]:[],{role:"assistant",content:x,tool_calls:s},...e];t.debug("继续对话,新 history 长度:",n.length),g="",y={...y,history:n},p=void 0,x=""}}}finally{d=null}},cancel(){d&&(d.abort(),d=null)},setCwd(e){c().setCwd(e)},getSessions:async()=>c().getSessions(),getSession:async e=>c().getSession(e),createSession:async e=>c().createSession(e),updateSession:async(e,s)=>c().updateSession(e,s),async deleteSession(e){await c().deleteSession(e)},getMessages:async e=>c().getMessages(e),saveMessage:async e=>c().saveMessage(e),async updateMessage(e){await c().updateMessage(e)},async deleteMessagesAfter(e,s){await c().deleteMessagesAfter(e,s)},async deleteMessagesAfterMessageId(e,s){await c().deleteMessagesAfterMessageId(e,s)},getOperations:async e=>c().getOperations(e),getTrashItems:async()=>c().getTrashItems(),restoreFromTrash:async e=>c().restoreFromTrash(e),listDir:async e=>c().listDir(e),exists:async e=>c().exists(e),stat:async e=>c().stat(e),readFile:async e=>c().readFile(e),readFileBase64:async e=>c().readFileBase64(e),homeDir:async()=>c().homeDir(),resolvePath:async e=>c().resolvePath(e),parentDir:async e=>c().parentDir(e),watchDir:async e=>c().watchDir(e),unwatchDir:async e=>c().unwatchDir(e),onDirChange:e=>c().onDirChange(e),async getSetting(e){const s=c();return s.getSetting?s.getSetting(e):null},async setSetting(e,s){const t=c();t.setSetting&&await t.setSetting(e,s)},async getAllSettings(){const e=c();return e.getAllSettings?e.getAllSettings():{}},async deleteSetting(e){const s=c();s.deleteSetting&&await s.deleteSetting(e)},async getIndexStats(){const e=c();return e.getIndexStats?e.getIndexStats():{totalDocuments:0,indexSize:0,lastUpdated:null}},async getIndexStatus(){const e=c();return e.getIndexStatus?e.getIndexStatus():{isIndexing:!1,lastProgress:null}},async syncIndex(){const e=c();return e.syncIndex?e.syncIndex():{success:!1}},async cancelIndex(){const e=c();return e.cancelIndex?e.cancelIndex():{success:!1}},async deleteIndex(){const e=c();return e.deleteIndex?e.deleteIndex():{success:!1}},async registerIndexListener(){const e=c();return e.registerIndexListener?e.registerIndexListener():{success:!1}},async unregisterIndexListener(){const e=c();return e.unregisterIndexListener?e.unregisterIndexListener():{success:!1}},onIndexProgress(e){const s=c();return s.onIndexProgress?s.onIndexProgress(e):()=>{}},onToolApprovalRequest:e=>()=>{},async respondToolApproval(e,s){},async asrStart(e){const s=c();return s.asrStart?s.asrStart(e):{success:!1,error:"ASR not supported"}},async asrSendAudio(e){const s=c();return s.asrSendAudio?s.asrSendAudio(e):{success:!1,error:"ASR not supported"}},async asrFinish(){const e=c();return e.asrFinish?e.asrFinish():{success:!1,error:"ASR not supported"}},async asrStop(){const e=c();return e.asrStop?e.asrStop():{success:!0}},async asrStatus(){const e=c();return e.asrStatus?e.asrStatus():{connected:!1}},async asrWarmup(e){const s=c();return s.asrWarmup?s.asrWarmup(e):{success:!1,error:"ASR not supported"}},onAsrConnected(e){const s=c();return s.onAsrConnected?s.onAsrConnected(e):()=>{}},onAsrResult(e){const s=c();return s.onAsrResult?s.onAsrResult(e):()=>{}},onAsrError(e){const s=c();return s.onAsrError?s.onAsrError(e):()=>{}},onAsrClosed(e){const s=c();return s.onAsrClosed?s.onAsrClosed(e):()=>{}},async openExternal(e){const s=c();if(s.openExternal)return s.openExternal(e)}}}export{n as createElectronAdapter,r as createHybridAdapter,s as createLogger};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huyooo/ai-chat-bridge-electron",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.41",
|
|
4
4
|
"description": "AI Chat Electron Bridge - IPC integration for Electron apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/main/index.js",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"clean": "rm -rf dist"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@huyooo/ai-chat-core": "^0.2.
|
|
34
|
-
"@huyooo/ai-chat-storage": "^0.2.
|
|
35
|
-
"@huyooo/ai-chat-types": "^0.2.
|
|
33
|
+
"@huyooo/ai-chat-core": "^0.2.41",
|
|
34
|
+
"@huyooo/ai-chat-storage": "^0.2.41",
|
|
35
|
+
"@huyooo/ai-chat-types": "^0.2.41",
|
|
36
36
|
"uuid": "^11.1.0",
|
|
37
37
|
"ws": "^8.18.3"
|
|
38
38
|
},
|