-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsignal-lm-safe-writes.js
More file actions
21 lines (21 loc) · 5 KB
/
Copy pathsignal-lm-safe-writes.js
File metadata and controls
21 lines (21 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(function(){
if(window.__signalLmSafeWritesInstalled)return;
window.__signalLmSafeWritesInstalled=true;
var N=['SignalLMNativeBridge','lmStudioLiteNative','NativeFileBridge','AndroidBridge','AndroidFileBridge','AndroidWorkspaceBridge'];
function bridge(){for(var i=0;i<N.length;i++){var b=window[N[i]];if(b&&typeof b==='object')return b;}return null;}
function json(v){if(typeof v!=='string')return v;var s=v.trim();if(!s||'{['.indexOf(s[0])<0)return v;try{return JSON.parse(s);}catch(e){return v;}}
function path(v){return String(v||'').replace(/\\/g,'/').replace(/^\/+/, '').replace(/\/+/g,'/').trim();}
function known(){var s=new Set();try{(Array.isArray(window.workspaceFiles)?window.workspaceFiles:[]).forEach(function(f){var p=path(f&&f.path);if(p)s.add(p.toLowerCase());});}catch(e){}try{document.querySelectorAll('.workspace-file-chip,.file-path,[data-workspace-path]').forEach(function(n){var p=path(n.getAttribute('data-workspace-path')||n.textContent||'');if(p)s.add(p.toLowerCase());});}catch(e){}return s;}
function one(o){if(!o||typeof o!=='object')return null;var p=path(o.path||o.file||o.name||o.relativePath),c=Object.prototype.hasOwnProperty.call(o,'content')?o.content:Object.prototype.hasOwnProperty.call(o,'newContent')?o.newContent:Object.prototype.hasOwnProperty.call(o,'replacement')?o.replacement:o.text;if(!p)return null;if(c==null)return{path:p,error:'missing content'};c=String(c);if(c.length===0)return{path:p,error:'empty content'};return{path:p,content:c};}
function list(v){var x=json(v),src=Array.isArray(x)?x:Array.isArray(x&&x.files)?x.files:Array.isArray(x&&x.edits)?x.edits:[],m=new Map(),errs=[];src.forEach(function(i){var e=one(i);if(!e)return;if(e.error){errs.push(e.path+' ('+e.error+')');return;}m.set(e.path,e);});if(errs.length)throw new Error('Blocked unsafe write: '+errs.join(', '));var out=Array.from(m.values());if(!out.length)throw new Error('Blocked unsafe write: no complete file content was available yet.');var k=known();if(k.size){var bad=out.filter(function(e){return !k.has(e.path.toLowerCase());});if(bad.length)throw new Error('Blocked unsafe write outside the selected workspace list: '+bad.map(function(e){return e.path;}).join(', '));}return out;}
function single(p,c){var e=one({path:p,content:c});if(!e||e.error)throw new Error('Blocked unsafe write: '+path(p||'file')+' has no complete content.');var k=known();if(k.size&&!k.has(e.path.toLowerCase()))throw new Error('Blocked unsafe write outside the selected workspace list: '+e.path);return e;}
function count(r){var x=json(r);if(typeof x==='number')return x;if(x&&typeof x.count==='number')return x.count;if(x&&typeof x.written==='number')return x.written;if(x===true||x==='true')return null;return null;}
function notice(e){var msg=e&&e.message?e.message:String(e||'Write failed.');try{if(window.SignalLMChatCommands&&typeof window.SignalLMChatCommands.toast==='function'){window.SignalLMChatCommands.toast(msg);return;}}catch(_){}try{var t=document.getElementById('toast');if(t){t.textContent=msg;t.classList.add('show');setTimeout(function(){t.classList.remove('show');},3500);}}catch(_){}}
function patchBridge(){var b=bridge();if(!b||b.__signalLmSafeWritesPatched)return false;var changed=false;if(typeof b.writeFiles==='function'){var wf=b.writeFiles;b.writeFiles=function(payload){var edits;try{edits=list(payload);}catch(e){notice(e);return Promise.reject(e);}return Promise.resolve(wf.call(this,{files:edits})).then(function(r){var n=count(r);if(n!==null&&n!==edits.length)throw new Error('Native write only saved '+n+' of '+edits.length+' file(s). No pending edit was cleared.');return r;});};changed=true;}if(typeof b.writeFile==='function'){var w1=b.writeFile;b.writeFile=function(p,c){var e;try{e=single(p,c);}catch(err){notice(err);return Promise.reject(err);}return Promise.resolve(w1.call(this,e.path,e.content));};changed=true;}if(changed)b.__signalLmSafeWritesPatched=true;return changed;}
function validProp(prop){var edits=[];try{edits=Array.isArray(window[prop])?window[prop]:[];}catch(e){}if(!edits.length)return;try{window[prop]=list(edits);}catch(e){notice(e);throw e;}}
function wrap(name,prop){var fn=window[name];if(typeof fn!=='function'||fn.__signalLmSafeWritesWrapped)return false;var w=function(){try{validProp(prop);}catch(e){return Promise.reject(e);}return fn.apply(this,arguments);};w.__signalLmSafeWritesWrapped=true;window[name]=w;return true;}
function patchApply(){wrap('applyPendingEdits','pendingEdits');wrap('applyAiFolderEdits','pendingAiChanges');if(window.SignalLMChatCommands&&typeof window.applyPendingEdits==='function')window.SignalLMChatCommands.applyPendingEdits=window.applyPendingEdits;}
function install(){patchBridge();patchApply();}
install();window.addEventListener('DOMContentLoaded',install);window.addEventListener('load',install);window.addEventListener('workspaceSelected',function(){setTimeout(install,50);});var tries=0,t=setInterval(function(){tries++;install();if(tries>=80)clearInterval(t);},150);
window.SignalLMSafeWrites={install:install,normalizeEditList:list,getKnownWorkspacePaths:known};
})();